请参考下面的代码.
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 TaskGetStringAsync() { 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应该与之前不同.为什么结果是一样的?在控制台应用程序中,线程ID是不同的,但在WPF应用程序中,它们是相同的.有人可以帮忙吗?
async/await的一个重点是,如果你有一个SynchronizationContext,比如WPF DispatcherSynchronizationContext
,那么在await之后,该线程上的工作将在该线程上继续,除非你告诉它不要.
控制台应用程序没有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 TaskGetStringAsync() { 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
.
有关详细信息,请参阅artice" 它是关于SynchronizationContext的全部内容 ".