任务延迟是否创建新线程?
Does Task delay create new Thread?
请问下面的Task.Delay调用Task.Run是线程id改变的原因还是背后的逻辑不同?
async Task Main()
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId); //11
await Task.Delay(200);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId); //22
}
不,Task.Delay
不调用下面的 Task.Run
。它只是 returns 一个 Task
在指定的持续时间后完成,并在内部调用任何 continuations that are attached to it on the ThreadPool
. It uses a System.Threading.Timer
。它的实现如下所示:
public class Task
{
public static Task Delay(int millisecondsDelay)
{
var tcs = new TaskCompletionSource();
_ = new Timer(_ => tcs.SetResult(), null, millisecondsDelay, -1);
return tcs.Task;
}
}
因此,当您 await
Task.Delay
时,await
之后的延续运行在调用 Timer
回调的同一线程上¹,这恰好是一个ThreadPool
个线程。
注:以上实现只是一个例子。这不是实际的实现,也不能保证能正常工作。 Timer
实例未存储在任何地方,因此它可能会在调用回调之前被垃圾收集,从而导致 never-completing Task
.
¹ 假设没有 SynchronizationContext
。
请问下面的Task.Delay调用Task.Run是线程id改变的原因还是背后的逻辑不同?
async Task Main()
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId); //11
await Task.Delay(200);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId); //22
}
不,Task.Delay
不调用下面的 Task.Run
。它只是 returns 一个 Task
在指定的持续时间后完成,并在内部调用任何 continuations that are attached to it on the ThreadPool
. It uses a System.Threading.Timer
。它的实现如下所示:
public class Task
{
public static Task Delay(int millisecondsDelay)
{
var tcs = new TaskCompletionSource();
_ = new Timer(_ => tcs.SetResult(), null, millisecondsDelay, -1);
return tcs.Task;
}
}
因此,当您 await
Task.Delay
时,await
之后的延续运行在调用 Timer
回调的同一线程上¹,这恰好是一个ThreadPool
个线程。
注:以上实现只是一个例子。这不是实际的实现,也不能保证能正常工作。 Timer
实例未存储在任何地方,因此它可能会在调用回调之前被垃圾收集,从而导致 never-completing Task
.
¹ 假设没有 SynchronizationContext
。