我正在开发一个由两个团队开发的非常大的项目,一个(主要)用于数据库,一个(我在哪里)主要用于GUI和辅助类作为GUI和DB之间的接口。 显然,沟通中存在错误,当然 - 我们不能假设100Mbit带宽&超高速服务器计算机。
语言是C#.NET,目标"框架"是WPF 和 Silverlight。
当用户单击按钮时,GUI会向DB(通过帮助程序类)询问信息。让我们说...披萨类型。服务器应该回答" {Funghi,Frutti di mare,Prosciutto}" 。当DB发送他的答案时,我们会收到一个" database.Ready"事件并填写我们的数据网格。
但是如果用户在尚未收到答案的情况下点击按钮,则GUI会向数据库发送另一个请求。整个系统试图为用户服务。 但它不能,因为当第二个请求被发送时,第一个请求在我们想要读取时被处理掉。所以发生 NullReferenceExceptions 。
我通过实现一种信号量来解决这个问题,信号量在用户输入发生时关闭,并在Ready事件(它调用的函数)完成工作时打开。
问题: 如果我没有收到Ready事件,则不允许用户输入,但这是错误的。
问题: 是否有一个共同的(或至少是工作的)解决方案来停止等待Ready事件......
1)重新发送请求几次,希望我们收到我们的披萨类型?
和/或
2)删除请求,告诉用户数据库无法发送答案,并重新打开信号量?
我不能在这里发布代码,因为这段代码是公司的财产,我更喜欢有理论上的解决方案,这对专业人士来说也是可以的。
对于这篇长篇文章感到抱歉,感谢您的回答!
答案 0 :(得分:0)
我假设您已经在使用后台线程将查询分派到数据库并等待它的响应。您可以使用.NET 4.0中引入的Task
API来取消此类请求。为此,您传入一个CancellationToken
,表示状态为执行任务。您可以通过CancellationToken
获取CancellationTokenSource
,如以下代码所示:
public partial class MainWindow : Window
{
private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
public MainWindow()
{
InitializeComponent();
}
private void Button_CallDatabase(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(CallDatabase, _cancellationTokenSource.Token);
}
private void Button_OnNavigate(object sender, RoutedEventArgs e)
{
// If you navigate, you can cancel the background task and thus
// it will not execute any further
_cancellationTokenSource.Cancel();
}
private void CallDatabase()
{
// This simulates a DB call
for (var i = 0; i < 50; i++)
{
Thread.Sleep(100);
}
// Check if cancellation was requested
if (_cancellationTokenSource.Token.IsCancellationRequested)
{
Debug.WriteLine("Request cancelled");
return;
}
Debug.WriteLine("Update Controls with DB infos.");
}
}
请注意,此示例已简化,您可以并且应该在另一个组件(例如视图模型)中使用它。
如果您仍想使用Ready事件,您也可以在离开时从中取消注册,以便在引发时不再执行任何操作。