.net和parallel。例外绕过“试品”堵塞
有人可以解释该代码的行为:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello world");
try
{
Parallel.ForEach(new[] { 1, 2, 3 }, async i =>
{
await Task.Delay(TimeSpan.FromSeconds(3));
throw new TaskCanceledException();
});
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.WriteLine("Goodbye cruel world");
Console.ReadLine();
}
}
如何可能,异常在主线程中弹出“ try”块和应用程序下降。 我知道平行异步的最佳方法是“任务。”。问题的目的是了解行为。
Can somebody explain the behaviour of this code:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello world");
try
{
Parallel.ForEach(new[] { 1, 2, 3 }, async i =>
{
await Task.Delay(TimeSpan.FromSeconds(3));
throw new TaskCanceledException();
});
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.WriteLine("Goodbye cruel world");
Console.ReadLine();
}
}
How can it be possible, the exception pops up in the main thread out of "try" block and application fall.
I knew the best way for parallel async is "Task.WhenAll". The goal of the question is to understand the behaviour.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Parallel.Foreach
不能用于调用异步方法。它仅用于内存数据并行性,而不是异步操作。它通过分区数据并将每个批次送入工人任务,使用每个CPU核心大约一个工人来工作。它甚至使用调用线程来处理其中一个分区,这就是为什么它似乎正在“阻止”。它的过载都不接受
task
,这意味着在这种情况下,lambda的返回类型为async void
。问题代码等效于:
async void
无法等待方法,这意味着他们的例外也无法被呼叫者抓住。此代码启动3async void
使用并立即返回。在.NET 6中,您应该使用
Parallel.ForeachAsync
:Parallel.ForEach
can't be used to call asynchronous methods. It's only meant for in-memory data parallelism, not asynchronous operations. It works by partitioning its data and feeding each batch to a worker task, using roughly one worker per CPU core. It even uses the calling thread to process one of those partitions, which is why it seems to be "blocking".None of its overloads accepts a
Task
which means the return type of the lambda in this case isasync void
.The question's code is equivalent to :
async void
methods can't be awaited which means their exceptions can't be caught by the caller either. This code fires off 3async void
calls using and returns immediately.In .NET 6 you should use
Parallel.ForEachAsync
instead :