如何从非异步方法调用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);
}
}
答案 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