为什么调用方方法和异步方法具有相同的线程id
本文关键字:id 线程 异步方法 方方法 调用 方法 为什么 | 更新日期: 2023-09-27 18:29:15
请参阅下面的代码。
public MainViewModel()
{
LongRunningOperationCommand = new RelayCommand(ExecuteLongRunningOperationCommand);
}
private void ExecuteLongRunningOperationCommand()
{
Test();
}
private async Task Test()
{
Log += "Command begin: " + DateTime.Now + "'r'n";
Log += "Command thread: " + Thread.CurrentThread.ManagedThreadId + "'r'n";
var getStringAsync = GetStringAsync();
Log += "Work in Command...'r'n";
Log += "Work in Command which not related to the result of async method will complete: " + DateTime.Now + "'r'n";
Log += "Work in Command which not related to the result of async method will complete, thread: " +
Thread.CurrentThread.ManagedThreadId + "'r'n";
string result = await getStringAsync;
Log += "Command will complete: " + DateTime.Now + "'r'n";
Log += "Command will complete, thread: " + Thread.CurrentThread.ManagedThreadId + "'r'n";
Log += result + "'r'n";
}
private async Task<string> GetStringAsync()
{
Log += "Async method begin: " + DateTime.Now + "'r'n";
Log += "Async method thread: " + Thread.CurrentThread.ManagedThreadId + "'r'n";
Log += "Work in Async method... 'r'n";
await Task.Delay(10000);
Log += "Async method will complete: " + DateTime.Now + "'r'n";
Log += "Async method will complete, thread: " + Thread.CurrentThread.ManagedThreadId + "'r'n";
return "GetStringAsync method completed!";
}
结果如下
Command begin: 1/6/2016 11:58:37 PM
Command thread: 8
Async method begin: 1/6/2016 11:58:37 PM
Async method thread: 8
Work in Async method...
Work in Command...
Work in Command which not related to the result of async method will complete: 1/6/2016 11:58:37 PM
Work in Command which not related to the result of async method will complete, thread: 8
Async method will complete: 1/6/2016 11:58:47 PM
Async method will complete, thread: 8
Command will complete: 1/6/2016 11:58:47 PM
Command will complete, thread: 8
GetStringAsync method completed!
GetStringAsync方法中等待Task.Delay之后的线程id应与之前不同。为什么结果是一样的?在Console应用程序中,线程ID是不同的,但在WPF应用程序中它们是相同的。有人能帮忙吗?
async/await的一个要点是,如果你有一个SynchronizationContext,比如WPF的DispatcherSynchronizationContext
,那么在等待之后,在该线程上开始的工作将继续在该线程中进行,除非你告诉它不要这样做。
控制台应用程序没有SynchronizationContext,因此它使用默认上下文来调度线程池上的线程,这就是为什么您可以看到与WPF和控制台应用程序不同的行为。
为了告诉async/await它不需要保持在相同的同步上下文上,您可以在等待时使用.ConfigureAwait(false)
,如果需要,它将使用默认的线程池上下文进行回调。
private async Task Test()
{
Log += "Command begin: " + DateTime.Now + "'r'n";
Log += "Command thread: " + Thread.CurrentThread.ManagedThreadId + "'r'n";
var getStringAsync = GetStringAsync();
Log += "Work in Command...'r'n";
Log += "Work in Command which not related to the result of async method will complete: " + DateTime.Now + "'r'n";
Log += "Work in Command which not related to the result of async method will complete, thread: " +
Thread.CurrentThread.ManagedThreadId + "'r'n";
string result = await getStringAsync.ConfigureAwait(false);
Log += "Command will complete: " + DateTime.Now + "'r'n";
Log += "Command will complete, thread: " + Thread.CurrentThread.ManagedThreadId + "'r'n";
Log += result + "'r'n";
}
private async Task<string> GetStringAsync()
{
Log += "Async method begin: " + DateTime.Now + "'r'n";
Log += "Async method thread: " + Thread.CurrentThread.ManagedThreadId + "'r'n";
Log += "Work in Async method... 'r'n";
await Task.Delay(10000).ConfigureAwait(false);
Log += "Async method will complete: " + DateTime.Now + "'r'n";
Log += "Async method will complete, thread: " + Thread.CurrentThread.ManagedThreadId + "'r'n";
return "GetStringAsync method completed!";
}
注意,执行.ConfigureAwait(false)
并不能保证其余代码将在线程池中,如果任务处于Completed
状态,则代码将同步执行,并停留在最初称为await
的任何线程上。
有关更多信息,请参阅文章"It’s All About the SynchronizationContext"。