如果 async/await 没有创建新线程然后解释这段代码
If async/await doesn't create new thread then explain this code
我读过 this thread which claims with reference to msdn,认为 async/await 不会创建新线程。请看下面的代码:
static class Program
{
static void Main(string[] args)
{
var task = SlowThreadAsync();
for(int i = 0; i < 5; i++)
{
Console.WriteLine(i * i);
}
Console.WriteLine("Slow thread result {0}", task.Result);
Console.WriteLine("Main finished on thread {0}", Thread.CurrentThread.ManagedThreadId);
Console.ReadKey();
}
static async Task<int> SlowThreadAsync()
{
Console.WriteLine("SlowThreadAsync started on thread {0}", Thread.CurrentThread.ManagedThreadId);
await Task.Delay(2000);
Console.WriteLine("SlowThreadAsync completed on thread {0}", Thread.CurrentThread.ManagedThreadId);
return 3443;
}
}
作为这段代码的结果,我得到了不同的 ThreadId。为什么同一个线程得到不同的ThreadId?
您正在为示例使用控制台应用程序。这会极大地影响您的测试结果。控制台应用程序没有自定义 SynchronizationContext
(就像 Winforms、WPF 和 ASP.NET 一样),因此它使用 ThreadPoolTaskScheduler
在任意线程池线程上安排延续。在 UI 应用程序中尝试这个相同的示例,您将看到在同一线程上调用的延续。
您链接的文章试图传达的是,调用异步方法并不能保证任何代码运行在单独的线程上。所以如果你做想要保证这一点,你必须手动完成。特别是他们 不是 试图说异步方法将 总是 运行 在与调用方法 相同的线程上,因为在许多情况下,这显然是错误的。
我知道自问这个问题以来已经有一段时间了,但我 运行 解决了这个问题,并提供了有关 why/when 这种情况的更多详细信息。 await 的工作原理是,在等待的任务完成后,在线程池认为方便的任何线程上,将 await 之后的代码安排为 运行。通常这似乎与等待的任务在同一个线程上。不确定这与其他答案中提到的 SynchronizationContext
有何关系。
我注意到一个例外,当等待的任务很快完成时,似乎他们没有足够的时间将代码放在回调上,所以代码最终在第三个线程上被调用。
我读过 this thread which claims with reference to msdn,认为 async/await 不会创建新线程。请看下面的代码:
static class Program
{
static void Main(string[] args)
{
var task = SlowThreadAsync();
for(int i = 0; i < 5; i++)
{
Console.WriteLine(i * i);
}
Console.WriteLine("Slow thread result {0}", task.Result);
Console.WriteLine("Main finished on thread {0}", Thread.CurrentThread.ManagedThreadId);
Console.ReadKey();
}
static async Task<int> SlowThreadAsync()
{
Console.WriteLine("SlowThreadAsync started on thread {0}", Thread.CurrentThread.ManagedThreadId);
await Task.Delay(2000);
Console.WriteLine("SlowThreadAsync completed on thread {0}", Thread.CurrentThread.ManagedThreadId);
return 3443;
}
}
作为这段代码的结果,我得到了不同的 ThreadId。为什么同一个线程得到不同的ThreadId?
您正在为示例使用控制台应用程序。这会极大地影响您的测试结果。控制台应用程序没有自定义 SynchronizationContext
(就像 Winforms、WPF 和 ASP.NET 一样),因此它使用 ThreadPoolTaskScheduler
在任意线程池线程上安排延续。在 UI 应用程序中尝试这个相同的示例,您将看到在同一线程上调用的延续。
您链接的文章试图传达的是,调用异步方法并不能保证任何代码运行在单独的线程上。所以如果你做想要保证这一点,你必须手动完成。特别是他们 不是 试图说异步方法将 总是 运行 在与调用方法 相同的线程上,因为在许多情况下,这显然是错误的。
我知道自问这个问题以来已经有一段时间了,但我 运行 解决了这个问题,并提供了有关 why/when 这种情况的更多详细信息。 await 的工作原理是,在等待的任务完成后,在线程池认为方便的任何线程上,将 await 之后的代码安排为 运行。通常这似乎与等待的任务在同一个线程上。不确定这与其他答案中提到的 SynchronizationContext
有何关系。
我注意到一个例外,当等待的任务很快完成时,似乎他们没有足够的时间将代码放在回调上,所以代码最终在第三个线程上被调用。