Reputation: 2184
please refer to my code below.
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!";
}
The result as below
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!
The thread id after await Task.Delay in GetStringAsync method should be different with before. Why the result is the same? In Console application, the thread ids are different, but in WPF application, they're the same. Anyone can help?
Upvotes: 1
Views: 346
Reputation: 127603
One of the big points of async/await is if you have a SynchronizationContext, like the WPF's DispatcherSynchronizationContext
, work started on that thread will continue on that thread after the await unless you tell it not to.
Console applications do not have a SynchronizationContext so it uses the default context which schedules threads on the thread pool, that is why you see different behavior from WPF and a console app.
To tell async/await it does not need to keep on the same sync context you can use .ConfigureAwait(false)
when you await, it will then use the default thread pool context to do the callback if needed.
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!";
}
Note, doing .ConfigureAwait(false)
does not guarantee that the rest of the code will be on the thread pool, if the task is in the Completed
state the code will execute synchronously and stay on whatever thread originally called await
.
See the artice "It's All About the SynchronizationContext" for more info.
Upvotes: 6