使用 Task.WhenAll 时,Continuation 未在原始线程上运行

问题描述 投票:0回答:2

我试图了解一些关于哪些线程运行的信息。我的理解是,当我们使用await时,原始上下文被捕获并且延续将在原始线程上运行。这并不能证明我的情况是这样,请参阅下面的代码。

这是因为我正在使用net 6并且上下文在net core/net 6中不再重要了吗? (编辑:我将其作为控制台应用程序运行)

await DoSomething();
public async Task DoSomething()
{
    Console.WriteLine("Starting thread: " +Thread.CurrentThread.ManagedThreadId);
    var listofProcessor = new List<Processor> {
        new ("Processor"), new ("Processor1")
    };

    try
    {
        var tasks = listofProcessor.Select(x => x.Process());

        Console.WriteLine($"Before Task.WhenAll  {Thread.CurrentThread.ManagedThreadId}");
        await Task.WhenAll(tasks);
        Console.WriteLine($"After Task.WhenAll  {Thread.CurrentThread.ManagedThreadId}");
    }
    catch (Exception e)
    {
        Console.WriteLine("Exception caught");
    }
}
   
public class Processor 
{
    private string _name; 
    public Processor(string name) => _name = name;

    public async Task<string> Process()
    {
        Console.WriteLine($"{_name}.BeforeAwait {Thread.CurrentThread.ManagedThreadId}");
        await Task.Delay(100);
        Console.WriteLine($"{_name}.AfterAwait {Thread.CurrentThread.ManagedThreadId}");

        return "hellow";
    }
}

我希望

Console.WriteLine($"After Task.WhenAll xxx)
在原始线程上运行。但这并没有发生。结果是:

Starting thread: 1
Before Task.WhenAll  1
Processor.BeforeAwait 1
Processor1.BeforeAwait 1
Processor.AfterAwait 9
Processor1.AfterAwait 6
After Task.WhenAll  6
c# asynchronous .net-core async-await
2个回答
0
投票

原始上下文被捕获,延续将在原始线程上运行。

不。上下文不是线程。捕获上下文,然后在该上下文上运行延续。

对于控制台应用程序,上下文是线程池上下文,它将工作调度到线程池上。对于所有版本的 .NET 都是如此。


0
投票

我的理解是,当我们使用await时,原始上下文被捕获,并且延续将在原始线程上运行。

是的,如果存在执行这种同步的同步上下文,那么它就会产生这样的效果。示例是单线程的 UI 上下文,并在 UI 线程上运行延续。控制台应用程序没有同步上下文(或具有默认的线程池同步上下文),因此在同一线程上运行延续程序纯属巧合。实际上,我无法使用 .NET Framework 重现该行为 - 检查 demo fiddle

© www.soinside.com 2019 - 2024. All rights reserved.