.NET停止等待未到达的数据库事件 [英] .NET stop waiting for a database event which does not arrive

查看:146
本文介绍了.NET停止等待未到达的数据库事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个由两个团队(主要是数据库)和一个(我在哪里)开发的一个很大的项目,主要用于GUI和帮助类作为GUI和DB之间的接口。
显然,通信中有错误,当然 - 我们不能假设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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆