2015-10-26 221 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