我的问题是有关在Plinq下的 ForAll 方法中捕获异常
我试图同时设置最大线程数来运行任务。 使用 数不清的 .AsParallel() .WithDegreeOfParallelism(100) .ForAll(异步项目=>等待AsyncTask())
它可以工作,但是如果AsyncTask引发异常,则应用程序将崩溃。
我已经做了以下测试:
try
{
IEnumerable<string> enumerable = new List<string> { "st", "st" };
enumerable.AsParallel()
.ForAll(async f =>
{
try
{
throw new Exception(); // Or await AsyncTask that throws this
}
catch (Exception e)
{
e.ToString(); **// This Exception is captured**
throw e;
}
});
}
catch (Exception e) **// THIS IS NOT CAPTURED AND THE APP CRASHES**
{
e.ToString();
}
答案 0 :(得分:1)
enumerable.AsParallel()。ForAll()对枚举的每个元素并行执行给定操作。由于给定操作本身是异步的,因此ForAll()不会等到所有操作完成后再进行操作。在这种情况下,在您的AsyncTask()方法引发异常之前,执行的代码将离开try..catch块。这可能导致未处理的异常,从而使您的应用程序崩溃。
不要紧,您尝试等待AsyncTask(),因为ForAll()会获得简单的Action,而不会等待AsyncTask()的结果。
一个可能的解决方案是为每个没有AsParallel()。ForEach()的元素启动AsyncTask,然后在try..catch中等待结果。
存储
时Task or Task<T>
显示一个列表,您可以使用task.Exception属性检查是否有任何任务引发了异常。
您可以执行以下操作:
private async Task DoSomethingAsync()
{
try
{
IEnumerable<string> enumerable = new List<string> { "st", "st" };
// start all tasks and store them in an array
var tasks = enumerable.Select(TaskAsync).ToArray();
// do something more without waiting until all tasks above completed
// ...
// await all tasks
var completionTask = Task.WhenAll(tasks);
await completionTask;
// handle task exception if any exists
if (completionTask.Status == TaskStatus.Faulted)
{
foreach (var task in tasks)
{
if (task.Exception != null)
{
// throw an exception or handle the exception, e.g. log the exceptions to file / database
}
}
}
}
catch (Exception e)
{
// handle your exception, e.g. write a log to file / database
}
}
private Task TaskAsync(string item)
{
// Task.Delay() is just a placeholder
// do some async stuff here, e.g. access web services or a database
return Task.Delay(10000);
}