I have a problem understanding why the rest of the function after using async is done in different threads for the same code. Take an example - in CODE 1 the rest of the function is executed in thread 3, which is logical, because the DoAsyncWork function was executed in it.函数的其余部分在线程 3 中执行,这是合乎逻辑的,因为 DoAsyncWork 函数是在其中执行的。
In the case of CODE 2, the rest of the function is still executed in thread 1., although the function DoWorkAsync was done in thread 3.函数的其余部分仍然在线程 1 中执行,尽管函数 DoWorkAsync 在线程 3 中完成。
The only difference is that btnCallMethod_Click
is called from Windows Forms - it handles Click event for a standard button.
What does it depend on ? Does Windows Forms trigger events in any special way that the thread does not change?
//CODE 1:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp61
{
class Test
{
public event EventHandler Click;
public string TestString { get; set; }
internal void DoClick()
{
Click?.Invoke(this, new EventArgs());
}
public async void RunClick(object sender, EventArgs e)
{
Console.WriteLine("Before async call " + Thread.CurrentThread.ManagedThreadId); // Thread id=1
(sender as Test).TestString = await DoAsyncWork(1);
Console.WriteLine("After async call " + Thread.CurrentThread.ManagedThreadId); //Thread id=3 OK
}
private Task<string> DoAsyncWork(int step)
{
return Task.Run(() => {
Thread.Sleep(10000);
Console.WriteLine($"DoAsyncWork() " + Thread.CurrentThread.ManagedThreadId); //Thread id=3
return "555";
});
}
}
class Program
{
static async Task Main(string[] args)
{
Test x = new Test();
x.Click += x.RunClick;
x.DoClick();
Console.ReadKey();
}
}
}
/////////////////////////////////////////////////////////////////////
// CODE 2:
private async void btnCallMethod_Click(object sender, EventArgs e)
{
Console.WriteLine("step 1-" + Thread.CurrentThread.ManagedThreadId); //Thread id=1
this.Text = await DoWorkAsync();
Console.WriteLine("step 2-" + Thread.CurrentThread.ManagedThreadId); //Thread id=1 Still 1 !!! Why ? Should be 3
}
private async Task<string> DoWorkAsync()
{
return await Task.Run(() =>
{
Thread.Sleep(10000);
Console.WriteLine("step 99-" + Thread.CurrentThread.ManagedThreadId); // Thread id =3
return "Done with work!";
});
}
No, it shouldn't be 3 in the code 2
. It's all about synchronization context
.
There is no synchronization context
in console application, so task continuations are executed on thread pool in code 1
.
WPF
and WinForms
applications have synchronization context
to route execution back to UI
thread to modify controls for instance.
Try this this.Text = await DoWorkAsync().ConfigureAwait(false);
in the 2nd example and your code won't be returned to thread 1
.
Also check my answer here Is ConfigureAwait(false) required on all levels of the async chain when no real I/O call is involved?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.