TPL Как выполнить «обратный звонок» - PullRequest
5 голосов
/ 08 марта 2012

У меня есть небольшое приложение, которое должно проверять строки SQL-соединений на количество соединений (каждое из которых выполняется по одному).Для этого я временно установил ConnectionTimeout = 5, чтобы избежать длительного ожидания, если соединение недопустимо, и ConnectionTimeout = 0 (ждать вечно), скажем.

Чтобы избежать зависания пользовательского интерфейса, пока мы пытаемся Open()плохое соединение (даже при ConnectionTimeout = 5 ожидание SqlException может составлять до двадцати секунд), я хочу запустить тест в отдельном потоке, используя Task Parallel Library (TPL).Поэтому я добавляю новый поток, например:

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

Проблема в том, что он все еще блокирует пользовательский интерфейс (ясно), так как он ожидает результата, прежде чем вернуться к вызывающей стороне.Как я могу позволить коду вернуть управление в UI (освобождая GUI), получая при этом возможный результат от асинхронного Task?

Кроме того, из Task я могу законно сделать MessageBox.Show("Some message")?Это не работает для BackgroundWorkers, и этот объединенный поток по умолчанию является фоновым потоком;все же это не кажется проблемой.Спасибо за ваше время.

Ответы [ 2 ]

5 голосов
/ 08 марта 2012

Для TPL ContinueWith - это именно то, что вы хотите.Расширяя ответ Хенка:

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());
4 голосов
/ 08 марта 2012

Вы правы, вот где происходит ожидание:

 return asyncTestConn.Result;

Вы можете просто построить код завершения в хвосте TestConnection () или использовать продолжение:

// untested
//Task<bool> asyncTestConn = Task.Factory.Create<bool> (
Task<bool> asyncTestConn = new Task<bool> (
    () => TestConnection(conn, bShowErrMsg));
asyncTestConn.ContinueWith(MyFinishCode);
asyncTestConn.Start()

могу ли я законно сделать MessageBox.Show("Some message")?

На самом деле Да, MessageBox является поточно-ориентированным.Должно быть возможно и от Bgw.

Но вы значительно продлеваете жизнь Задаче, это не очень хорошая идея.

...