从非异步方法在并行方法中运行异步方法

时间:2015-10-26 09:10:48

标签: c# asynchronous async-await

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

下面的实现有效,但我已经读过不建议使用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 :(得分: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。如果您无法使调用代码异步,请先查看how to make asynchronous code play well with OOP上的博客系列。如果仍然无法使调用代码异步,请查看我的MSDN brownfield异步文章中的各种dubious hacks for mixing asynchronous and synchronous code

答案 1 :(得分:1)

如果要同步等待所有任务完成,请注意上下文:在每个等待的任务上使用ConfigureAwait(false)或等待不保存上下文的线程。

您可以使用Task.WaitAll方法。

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