当任务在调用线程上时,它是如何工作的
本文关键字:何工作 工作 调用 任务 线程 | 更新日期: 2023-09-27 18:22:06
正如我们所知,运行一个新的Task
并不能保证生成一个新线程。我想知道两块代码(任务调用者和任务的剩余代码)如何在同一个thread
上同时阻止调用者阻塞?
示例:
假设有一个窗体为Form1
的windows窗体应用程序。处理两个事件:KeyPress
,Click
this.KeyPreview = true;
...
private void Form1_Click(object sender, EventArgs e)
{
MessageBox.Show("Clicked");
}
private async void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
Console.WriteLine("Caller threadId = " + Thread.CurrentThread.ManagedThreadId);
await Task.Run(() =>
{
var start = DateTime.Now;
Console.WriteLine("working asynchronously on thread: " + Thread.CurrentThread.ManagedThreadId);
while ((DateTime.Now - start).TotalSeconds < 5)
;
});
}
如果我按下一个键,在5秒钟的时间里,控制台中有东西在写。同时该表单可以处理click
事件并显示消息框。
您可能会发现我的async
/await
帖子很有用。
正如其他人所指出的,async
和await
本身并不意味着多线程。但是,Task.Run
确实。
因此,当前代码在线程池线程上显式阻塞:
private async void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
// ** On the UI thread **
Console.WriteLine("Caller threadId = " + Thread.CurrentThread.ManagedThreadId);
await Task.Run(() =>
{
// ** On a thread pool thread **
Console.WriteLine("working asynchronously on thread: " + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(5);
});
// ** On the UI thread **
}
请注意,是Task.Run
-而不是await
-导致指定的代码在线程池线程上运行。
如果使用纯async
/await
而不使用Task.Run
,您将看到代码都在UI线程上运行:
private async void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
// ** On the UI thread **
Console.WriteLine("Caller threadId = " + Thread.CurrentThread.ManagedThreadId);
await DoNothingAsync();
// ** On the UI thread **
}
private async Task DoNothingAsync()
{
// ** On the UI thread **
Console.WriteLine("working asynchronously on thread: " + Thread.CurrentThread.ManagedThreadId);
await Task.Delay(5); // Task.Delay is the asynchronous version of Thread.Sleep
// ** On the UI thread **
}