.net和parallel。例外绕过“试品”堵塞

发布于 2025-02-04 06:30:40 字数 623 浏览 2 评论 0原文

有人可以解释该代码的行为:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

记忆で 2025-02-11 06:30:40

Parallel.Foreach不能用于调用异步方法。它仅用于内存数据并行性,而不是异步操作。它通过分区数据并将每个批次送入工人任务,使用每个CPU核心大约一个工人来工作。它甚至使用调用线程来处理其中一个分区,这就是为什么它似乎正在“阻止”。

它的过载都不接受task,这意味着在这种情况下,lambda的返回类型为async void

问题代码等效于:

async void Do(int i)
{
    await Task.Delay(TimeSpan.FromSeconds(3));
    throw new TaskCanceledException();
}

Parallel.ForEach(data,Do);

async void无法等待方法,这意味着他们的例外也无法被呼叫者抓住。此代码启动3 async void使用并立即返回。

在.NET 6中,您应该使用Parallel.ForeachAsync

var data=new[] { 1, 2, 3 };
await Parallel.ForEachAsync(data, async (i,token) =>
{
    await Task.Delay(TimeSpan.FromSeconds(3));
    throw new TaskCanceledException();
});

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 is async void.

The question's code is equivalent to :

async void Do(int i)
{
    await Task.Delay(TimeSpan.FromSeconds(3));
    throw new TaskCanceledException();
}

Parallel.ForEach(data,Do);

async void methods can't be awaited which means their exceptions can't be caught by the caller either. This code fires off 3 async void calls using and returns immediately.

In .NET 6 you should use Parallel.ForEachAsync instead :

var data=new[] { 1, 2, 3 };
await Parallel.ForEachAsync(data, async (i,token) =>
{
    await Task.Delay(TimeSpan.FromSeconds(3));
    throw new TaskCanceledException();
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文