2015-12-17 2 views
-1

Я хочу запускать несколько задач одновременно. Каждая задача возвращает тип значения.Поймать несколько обратных вызовов задачи через Continuewith

Может ли кто-нибудь сказать мне, как поймать все обратные вызовы через ContinueWith?

Мой тестовый код:

 static async Task<List<string>> ListAsync() 
     { 
      await Task.Delay(1000); 
      return new List<string>() { "Item 1", "Item 2" }; 
     } 

     static async Task<int> IntAsync() 
     { 
      await Task.Delay(1000); 
      return 10; 
     } 

     static async Task<string> StringAsync() 
     { 
      await Task.Delay(1000); 
      return "My string"; 
     } 

     static async Task Test() 
     { 
      Task t1 = StringAsync(); 
      Task t2 = IntAsync(); 
      Task t3 = ListAsync(); 
      await Task.WhenAny(t1, t2, t3).ContinueWith(t => 
      { 
       //how can I catch callbacks here? 
      }); 
     } 
+0

Я не уверен, что именно вы пытаетесь сделать. Не хотите ли вы назвать продолжение для всех трех задач? –

+0

@ZdeslavVojkovic Да. Я жду ответа от 3 задач. –

+2

* Почему вы не используете 'Task.WhenAll'? И почему вы смешиваете 'ContinueWith' с' await'? –

ответ

2

Если вы пытаетесь получить результаты всех задач, когда все они закончили, вы можете просто использовать Task.WhenAll. Если все задачи возвращают один и тот же результат, перегрузка Task.WhenAll(Task[] вернет задачу. В этом случае, await Task.WhenAll возвращает массив с результатом при решении текущих задач в следующем порядке:

var t1=Task.Run(()=>{...;return 1}); 
var t2=Task.Run(()=>{...;return 2}); 
var t3=Task.Run(()=>{...;return 3}); 

int[] results=await Task.WhenAll(t1,t2,t3); 
//Check t1's result 
Debug.Assert(results[0]==1); 

Когда задачи возвращают разные результаты, то Task.WhenAll(params Task[]) называется, который возвращает только задачу. Вы все еще можете получить доступ к результатам каждой задачи, хотя, используя его свойство Result withouth любой риск блокировки:

var t1=Task.Run(()=>{...;return 1}); 
var t2=Task.Run(()=>{...;return "Hi"}); 
var t3=Task.Run(()=>{...;return new[]{1,2,3}}); 

await Task.WhenAll(); 

Debug.Assert(t2.Result=="Hi"); 

Там нет причин использовать ContinueWith при использовании await, в ожидании делает примерно то же самое, используя ContinueWith - Он не запускает никаких асинхронных исполнений, он ожидает без блокировки для выполнения уже запущенных задач, он извлекает результаты и устанавливает контекст синхронизации в том, что было до того, как он был запущен.

+0

ya, я предпочитаю этот способ вместо использования 'foreach'. –

+0

Могу ли я задать небольшой вопрос? Я замечаю, что вы говорите о 'ContinueWith':' он извлекает результаты и устанавливает контекст синхронизации в том, что было до ожидаемого начала'. Почему «результаты» не содержат что-то вроде 't1.Result' или' t2.Result' или 't3.Result' в качестве вашей демонстрации? –

1

Если вы wan't называть задачи с различными продолжениями, вам необходимо указать продолжение для каждой задачи:

static async Task Test() 
{ 
    Task t1 = StringAsync().ContinueWith(t => System.Console.Out.WriteLine("string")); 
    Task t2 = IntAsync().ContinueWith(t => System.Console.Out.WriteLine("int")); 
    Task t3 = ListAsync().ContinueWith(t => System.Console.Out.WriteLine("list")); 
    await Task.WhenAny(t1, t2, t3); 
    // use WhenAll if you want to wait until all tasks are done 
} 

WhenAny будет завершена, когда какой-либо из выполняются дочерние задачи, а затем запускается продолжение, поэтому продолжение будет вызываться только один раз.

Если вы хотите вызвать функцию обратного вызова сразу после того, как все задачи завершены, самый простой способ заключается в следующем:

static async Task Test() 
{ 
    Task t1 = StringAsync(); 
    Task t2 = IntAsync(); 
    Task t3 = ListAsync(); 
    await Task.WhenAll(t1, t2, t3); 
    // your continuation logic here 
} 
+0

Нет причин для такого кода - 'WhenAny' вернет результаты задач в порядке –

+1

Кажется странным смешивать' ContinueWith' с 'async/await'. Для меня это обычно одно или другое решение, с сильным уклоном к последнему. – spender

+1

Я считаю, что OP думает, что WhenAny каким-то образом пересекает все задачи, но я не хотел слишком далеко перемещаться от исходного вопроса, –

Смежные вопросы