2015-10-26 3 views
0

Как вызвать методы async в paralell из метода non async? Мне также нужно ловить исключения, записывая их в вызывающий метод.Запуск методов async в paralell из метода non async

Выполнение ниже работает, но я прочитал, что WaitAny не рекомендуется, но я не смог заставить его работать, например, WhenAll.

Ps, «реальные» методы асинхронизации в моем приложении могут занять довольно много времени, около 10 минут.

class AsyncTest 
{ 

    public void RunAsyncInParalell() 
    { 
     var tasks = new List<Task>(); 

     var count = 500; 

     for(var i=0; i<count;i++) 
     { 
      tasks.Add(AsyncMethod(i));  
     } 

     while (tasks.Count() > 0) 
     { 
      var index = Task.WaitAny(tasks.ToArray()); 
      try 
      { 
       var res = tasks[index].Exception; 
       if (res != null) 
       { 
        res.Flatten(); 

        foreach (Exception ex in res.InnerExceptions) 
        { 
         Debug.WriteLine("ERROR: "+ ex.Message, ex); 
        } 
       } 
      } 
      catch (AggregateException aex) 
      { 

       aex = aex.Flatten(); 

       foreach (Exception ex in aex.InnerExceptions) 
       { 
        Debug.WriteLine("ERROR: " + ex.Message, ex); 
       } 
      } 
      catch (Exception ex) 
      { 
       Debug.WriteLine("ERROR: " + ex.Message, ex); 
      } 
      tasks.RemoveAt(index); 
     } 
    } 


    public async Task<int> AsyncMethod(int i) 
    { 
     var rnd = new Random(DateTime.Now.Millisecond); 
     int ticks = rnd.Next(0, 5000); 
     if (i == 50) 
     { 
      throw new Exception("Exception thrown for i=" + i); 
     } 
     await Task.Delay(ticks); 
     return (i); 
    } 
} 
+2

* Как я могу вызвать методы асинхронизации в paralell из неасинхронного метода? * Есть ли причина, по которой вы пытаетесь это сделать? Я предполагаю, что вы не можете изменить метод вызова? –

+0

Почему бы не включить 'Tasks.WaitAll (tasks.ToArray())' в блок try/catch, я думаю, что это работает. – DavidG

+0

IMHO Я бы предложил donot mix синхронизировать и асинхронный код – Eldho

ответ

1

Если вы хотите синхронно ждать все задачи, чтобы закончить, остерегайтесь контекста: использовать ConfigureAwait(false) на каждой долгожданного задачи или ждать в потоке, который не содержит контекст.

Вы можете использовать метод Task.WaitAll.

Task.WaitAll(tasks.ToArray()); 
// Then iterate over tasks to get results 
2

Как вызывать методы асинхронных параллельно с метода, не асинхронным?

Лучший ответ - «вы этого не сделаете». Вы можете, однако, называют асинхронные методы одновременно из другого асинхронного метода:

public async Task RunAsync() 
{ 
    var tasks = new List<Task>(); 
    var count = 500; 
    for (var i = 0; i < count; ++i) 
    tasks.Add(CallMethodAsync(i)); 

    await Task.WhenAll(tasks); 
} 

private async Task CallMethodAsync(int i) 
{ 
    try 
    { 
    await AsyncMethod(i); 
    } 
    catch (Exception ex) 
    { 
    Debug.WriteLine("ERROR: "+ ex.Message, ex); 
    throw; // TODO: Decide if this is the behavior you want. 
    } 
} 

Правильный способ вызова RunAsync это с await. Если вы не можете сделать код вызова async, сначала проверьте мою серию блога на how to make asynchronous code play well with OOP. Если вы все еще не можете сделать код вызова async, а затем проверьте различные dubious hacks for mixing asynchronous and synchronous code в моей асинхронной статье в MSDN brownfield.

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