Соответствующая структура для вызова Task.Factory.ContinueWhenAll - PullRequest
2 голосов
/ 03 марта 2012

Я хочу убедиться, что я использую ContinueWhenAll соответствующим образом.У меня есть несколько вызовов, которые будут выполняться асинхронно, а затем я хочу завершить выполнение конечной задачи только после успешного завершения других задач и после выполнения некоторых проверок результатов, чтобы увидеть, следует ли мне вместо этого прекратить обработку и вернуть запрещенный HTTPрезультат.В чем я не уверен, так это в том, будет ли последняя строка на самом деле ждать завершения всех других задач, или мне нужно структурировать ее по-другому.Если да, то как должна быть структурирована последняя строка, чтобы она вызывалась ТОЛЬКО в случае, если я прошёл оценку if (getPlatformTask.Result ...

// run some tasks and then gather them here
Task.Factory.ContinueWhenAll(new Task[]{ getPlatformTask, getUserTask },
    (tasks) =>
    {
        Task.WaitAll(tasks);

        if (getPlatformTask.Result == null || getUserTask.Result == null)
        {
           return Task<HttpResponseMessage>.Factory.StartNew(() =>
           {
              return new HttpResponseMessage(HttpStatusCode.Forbidden);
           });
        }
    });

// will this line below get called before the inner task above completes?   
return base.SendAsync(request, cancellationToken);       

1 Ответ

3 голосов
/ 03 марта 2012

Если вы хотите заблокировать текущий поток до завершения всех задач, вы можете просто использовать Task.WaitAll(), не нужно использовать задачи продолжения.Но имейте в виду, что заблокированный поток - это поток, который не использует ничего, кроме использования ресурсов (например, памяти).Блокировка потока часто проще, но менее эффективен.

Код может выглядеть следующим образом:

// run the tasks

Task.WaitAll(getPlatformTask, getUserTask);

// process the results

return base.SendAsync(request, cancellationToken);

И нет, в вашей версии последняя строка может (искорее всего, выполнится до того, как все задачи будут выполнены.ContinueWhenAll() не блокирует, вот и весь смысл.

РЕДАКТИРОВАТЬ: Я только что понял, что ваш метод возвращает Task.Таким образом, вам на самом деле не нужно блокировать поток, вместо этого вы можете вернуть Task, который завершен, когда вся работа завершена.Это может выглядеть так:

// run the tasks

var result = Task.Factory.ContinueWhenAll(
    new[] { getPlatformTask, getUserTask },
    _ =>
    {
        // process the results

        return base.SendAsync(request, cancellationToken);
    });

return result.Unwrap();

Здесь result - это Task<Task<HttpResponseMessage>>, но вам нужно просто Task<HttpResponseMessage>.Для этого вы можете использовать метод Unwrap() .

...