Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TPL How to Perform a 'Call-Back'

I have a small application that needs to test SQL connection strings for a number of connections (each done one-at-a-time). To do this I set the ConnectionTimeout = 5 temporarily to avoid a long wait if the connection is not valid and ConnectionTimeout = 0 (wait forever), say.

To avoid the UI hanging whilst we attempt to Open() a bad connection (even with ConnectionTimeout = 5 the wait for the SqlException can be up to twenty seconds), I want to run the test on a separate thread using Task Parallel Library (TPL). So I spin-off my new thread like:

Task<bool> asyncTestConn = Task.Factory.StartNew<bool>
    (() => TestConnection(conn, bShowErrMsg));
return asyncTestConn.Result;

The problem is that this is still locking the UI (clearly), as it is waiting for the result before returning to the caller. How do I allow the code to return control to the UI (freeing up the GUI) whilst getting the eventual result from the asynchronous Task?

Also, from within a Task can I legitimately do MessageBox.Show("Some message")? This does not work for BackgroundWorkers and this pooled-thread is a background thread by default; yet it does not seem to be a problem. Thanks for your time.

like image 412
MoonKnight Avatar asked Mar 08 '12 12:03

MoonKnight


1 Answers

For the TPL, ContinueWith is exactly what you want. Expanding on Henk's answer:

var asyncTestConn = Task.Factory.StartNew(() => TestConnection(conn, bShowErrMsg));
// Henk's "MyFinishCode" takes a parameter representing the completed
// or faulted connection-testing task.
// Anything that depended on your "return asyncTestConn.Result;" statement
// needs to move into the callback method.
asyncTestConn.ContinueWith(task =>
    {
        switch (task.Status)
        {
            // Handle any exceptions to prevent UnobservedTaskException.
            case TaskStatus.Faulted: /* Error-handling logic */ break;
            case TaskStatus.RanToCompletion: /* Use task.Result here */ break;
        }
    },
    // Using this TaskScheduler schedules the callback to run on the UI thread.
    TaskScheduler.FromCurrentSynchronizationContext());
like image 117
anton.burger Avatar answered Oct 05 '22 23:10

anton.burger