2015-10-26 166 views
0

如何从非异步方法调用并行中的异步方法?我还需要捕获异常并将它们记录在调用方法中。从非异步方法在并行中运行异步方法

下面的实现工作,但我读过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

*如何从非异步方法调用并行方式的异步方法?*是否有任何理由试图做到这一点?我假设你不能改变调用方法? –

+0

为什么不将'Tasks.WaitAll(tasks.ToArray())'包装在try/catch块中,我认为这是有效的。 – DavidG

+0

恕我直言,我会建议donot混合同步和异步代码 – 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. 
    } 
} 

正确的方法来调用RunAsyncawait。如果你不能使调用代码异步,那么首先看看我的博客系列how to make asynchronous code play well with OOP。如果仍然无法使调用代码异步,请查看我的MSDN棕色域异步文章中的各种dubious hacks for mixing asynchronous and synchronous code