.NET stop waiting for a database event which does not arrive

让人想犯罪 __ 提交于 2020-01-25 10:54:06

问题


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!


回答1:


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.



来源:https://stackoverflow.com/questions/25500908/net-stop-waiting-for-a-database-event-which-does-not-arrive

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!