我试图了解一些关于哪些线程运行的信息。我的理解是,当我们使用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
原始上下文被捕获,延续将在原始线程上运行。
不。上下文不是线程。捕获上下文,然后在该上下文上运行延续。
对于控制台应用程序,上下文是线程池上下文,它将工作调度到线程池上。对于所有版本的 .NET 都是如此。
我的理解是,当我们使用await时,原始上下文被捕获,并且延续将在原始线程上运行。
是的,如果存在执行这种同步的同步上下文,那么它就会产生这样的效果。示例是单线程的 UI 上下文,并在 UI 线程上运行延续。控制台应用程序没有同步上下文(或具有默认的线程池同步上下文),因此在同一线程上运行延续程序纯属巧合。实际上,我无法使用 .NET Framework 重现该行为 - 检查 demo fiddle。