C# 相同代码的等待和不同线程id
我很难理解为什么在使用async之后,函数的其余部分在同一代码的不同线程中完成。例如,在代码1中,RunClick函数的其余部分在线程3中执行,这是合乎逻辑的,因为DoAsyncWork函数是在线程3中执行的 在代码2的情况下,btnCallMethod_Click函数的其余部分仍然在线程1中执行,尽管函数DoWorkAsync是在线程3中执行的 唯一的区别是,C# 相同代码的等待和不同线程id,c#,async-await,C#,Async Await,我很难理解为什么在使用async之后,函数的其余部分在同一代码的不同线程中完成。例如,在代码1中,RunClick函数的其余部分在线程3中执行,这是合乎逻辑的,因为DoAsyncWork函数是在线程3中执行的 在代码2的情况下,btnCallMethod_Click函数的其余部分仍然在线程1中执行,尽管函数DoWorkAsync是在线程3中执行的 唯一的区别是,btnCallMethod\u单击 从Windows窗体调用-它处理标准按钮的单击事件 这取决于什么?Windows窗体是否以线程不更改
btnCallMethod\u单击
从Windows窗体调用-它处理标准按钮的单击事件
这取决于什么?Windows窗体是否以线程不更改的任何特殊方式触发事件
//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!";
});
}
//代码1:
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用系统线程;
使用System.Threading.Tasks;
名称空间控制台EAPP61
{
课堂测试
{
公共事件事件处理程序单击;
公共字符串TestString{get;set;}
内部void DoClick()
{
单击?.Invoke(这是新的EventArgs());
}
公共异步void RunClick(对象发送方,事件参数e)
{
Console.WriteLine(“异步调用之前”+Thread.CurrentThread.ManagedThreadId);//线程id=1
(发送方作为测试)。TestString=Wait-DoAsyncWork(1);
Console.WriteLine(“异步调用后”+Thread.CurrentThread.ManagedThreadId);//线程id=3 OK
}
私有任务DoAsyncWork(int步骤)
{
返回任务。运行(()=>{
睡眠(10000);
Console.WriteLine($“DoAsyncWork()”+Thread.CurrentThread.ManagedThreadId);//线程id=3
返回“555”;
});
}
}
班级计划
{
静态异步任务主(字符串[]args)
{
测试x=新测试();
x、 Click+=x.RunClick;
x、 DoClick();
Console.ReadKey();
}
}
}
/////////////////////////////////////////////////////////////////////
//代码2:
私有异步void btnCallMethod_单击(对象发送方,事件参数e)
{
Console.WriteLine(“步骤1-”+Thread.CurrentThread.ManagedThreadId);//线程id=1
this.Text=await-doworksync();
Console.WriteLine(“步骤2-”+Thread.CurrentThread.ManagedThreadId);//线程id=1还是1!!!为什么?应该是3
}
专用异步任务DoWorkAsync()
{
返回等待任务。运行(()=>
{
睡眠(10000);
Console.WriteLine(“步骤99-”+Thread.CurrentThread.ManagedThreadId);//线程id=3
返回“完成工作!”;
});
}
不,在代码2中不应该是3。这一切都是关于同步上下文的
控制台应用程序中没有同步上下文
,因此任务继续在code 1
中的线程池上执行
WPF
和WinForms
应用程序具有同步上下文
将执行路由回UI
线程以修改控件
试试这个this.Text=await-doworksync().ConfigureAwait(false)代码>在第二个示例中,您的代码将不会返回到线程1
请在这里检查我的答案
您是否在问为什么await
在UI中的同一个线程中继续,但如果不是UI,则在不同的线程中继续?您可以在中找到一些见解。在异步代码中使用Thread.Sleep()从来都不好-尝试将其替换为await Task.Delay(),并从DoWorkAsync()中删除不必要的Task.Run(),然后查看是否仍然得到相同的结果。是的,问题是:如果从UI调用方法,为什么await会在同一线程中继续,如果它是从我的私人课(活动)中调用的,为什么不呢。