.NET停止等待未到达的数据库事件 [英] .NET stop waiting for a database event which does not arrive
问题描述
显然,通信中有错误,当然 - 我们不能假设100Mbit的带宽&超快速的服务器计算机。
语言是C#.NET,目标框架是WPF 和 Silverlight。
当用户单击按钮时,GUI会通过帮助器类查询DB(信息)。让我们说...比萨饼类型。服务器应该回答{Funghi,Frutti di mare,Prosciutto}。当DB发送答案时,我们收到一个database.Ready事件并填写我们的datagrid。
但如果用户点击按钮,我们还没有收到答案,GUI会向数据库发送另一个请求。整个系统试图为用户服务。
但是它不能,因为当第二个请求被发送时,第一个被处理,当我们想要读取它。所以我们已经解决了这个问题,实现了一种在用户输入时关闭的信号量,当Ready事件发生时打开
问题:
如果我没有收到准备事件,则没有用户输入允许,但这是错误的。
问题:
是否有一个常见(或至少是工作)解决方案停止等待准备事件和...
1)重新发送请求几次,希望我们收到我们的比萨类型? p>
AND / OR
2)删除请求,告诉用户数据库发送答案失败,并重新 - 打开信号灯?
我不能在这里发布代码,因为这个代码是一个公司的财产,我宁愿有理论上的解决方案,这是可以的对于专业人士来说,
对于长篇文章,对不起,谢谢哟你的答案!
我假设你已经在使用后台线程将查询发送到数据库并等待它的响应。您可以使用.NET 4.0中引入的任务
API来取消此类请求。为此,您通过一个 CancellationToken
,将状态发送到执行任务。您可以通过 CancellationTokenSource
获得 CancellationToken
,如以下代码所示:
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)
{
//如果您导航,您可以取消后台任务,从而
//它不会再执行
_cancellationTokenSource.Cancel();
private void CallDatabase()
{
//这个模拟一个DB调用
for(var i = 0; i <50; i ++)
{
Thread.Sleep(100);
}
//检查是否要求取消
if(_cancellationTokenSource.Token.IsCancellationRequested)
{
Debug.WriteLine(Request cancelled) ;
返回;
}
Debug.WriteLine(使用DB信息更新控件);
}
}
请注意,这个例子是简化的,你可以而且应该在另一个组件(例如,视图模型)中使用它。
如果您仍然想使用Ready事件,您也可以在离开时取消注册,以便升级时不会执行进一步的操作。
I'm working on a really big project developed by two teams, one (mainly) for the database, and one (where I am) mainly for the GUI and helper classes as an interface between GUI and DB. Obviously, there are errors in communication, and - of course - we can't assume 100Mbit bandwidth & super-fast server computer.
Language is C# .NET, target "framework" is WPF and Silverlight.
When a user clicks a button, the GUI asks the DB (through helper classes) for information. Let's say... pizza types. The server should answer "{Funghi,Frutti di mare,Prosciutto}". When DB sends his answer, we receive a "database.Ready" event and fill our datagrid.
BUT if the user clicks the button while we haven't received the answer yet, the GUI sends an another request to the database. And the whole system tries to serve the user. But it can't, because when the second request is sent, the first is disposed when we want to read it. So NullReferenceExceptions occur.
I've solved this by implementing kind of a semaphore which closes when user input occurs and opens when the Ready event (the functions it calls) finishes working.
Problem: If I don't receive the Ready event, no user input is allowed, but this is wrong.
Question: Is there a common (or at least, working) solution to stop waiting for the Ready event and...
1) re-sending the request a few times, hoping we receive our pizza types?
AND/OR
2) Dropping the request, tell the user that database failed to send the answer, and re-open the semaphore?
I can't post code here as this code is the property of a corporation, I'd rather like to have theoretical solutions, which are okay for professionals too.
Sorry for the long post, and thank you for your answers!
I assume that you are already using a background thread to dispatch the query to the database and wait for it's response. You can use the Task
API that was introduced in .NET 4.0 to cancel such a request. For that, you pass in a CancellationToken
that signals the status to the executing task. You can obtain a CancellationToken
via a CancellationTokenSource
as shown in the following code:
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.");
}
}
Note that this example is simplified, you can and should use this in another component (e.g. view model).
If you still want to use the Ready event, you could also just unregister from it when you navigate away, so that no further actions will be performed when it is raised.
这篇关于.NET停止等待未到达的数据库事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!