未在线程池线程上计划任务继续
本文关键字:线程 任务 继续 计划 | 更新日期: 2023-09-27 18:30:24
我正在阅读有关SynchronizationContext及其与async/await方法一起使用的信息(链接)。据我了解,在同步上下文为空的控制台应用程序中,将使用默认调度程序(即线程池)调度等待的方法(任务)的继续。
但是,如果我运行此控制台应用,你将从输出中看到延续在我创建的工作线程上运行:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("MainThreadId=" + Thread.CurrentThread.ManagedThreadId);
Method1().ContinueWith(t =>
{
Console.WriteLine("After Method1. ThreadId=" + Thread.CurrentThread.ManagedThreadId);
});
Console.ReadKey();
}
public static async Task Method1()
{
Console.WriteLine("Method1 => Entered. ThreadId=" + Thread.CurrentThread.ManagedThreadId);
TaskCompletionSource<bool> completionSource = new TaskCompletionSource<bool>();
Thread thread = new Thread(() =>
{
Console.WriteLine("Method1 => Started new thread. ThreadId=" + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000);
completionSource.SetResult(true);
});
thread.Start();
await completionSource.Task;
Console.WriteLine("Method1 => After WorkerThread. ThreadId=" + Thread.CurrentThread.ManagedThreadId);
}
}
这是输出:
MainThreadId=10
Method1 => Entered. ThreadId=10
Method1 => Started new thread. ThreadId=11
Method1 => After WorkerThread. ThreadId=11
After Method1. ThreadId=12
如您所见,"After WorkerThread"与我的workerthread输出在同一线程上,但不在线程池上。
我发现了一个类似的问题,但这家伙正在使用 Mono,他们说这是一个错误。就我而言,我在Visual Studio中构建了这段代码,并在计算机上安装的Windows 7和.Net 4.5.2下运行它。
有人可以解释一下这种行为吗?
这是因为我在博客上记录了一个实现细节:await
创建的延续是使用 ExecuteSynchronously
标志调度的。在这种情况下,当需要触发延续时(即,在工作线程上的TaskCompletionSource<T>.SetResult
调用中),默认调度程序首先尝试确定它是否可以在当前线程上运行。
由于工作线程没有拒绝同步执行任务的TaskScheduler
,因此 ExecuteSynchronously
标志将导致线程池任务调度程序仅同步执行任务(即在调用线程上)。