我们知道运行新Task
并不能保证创建一个新线程。我想知道两个代码块(任务调用者和任务的剩余代码)在同一个thread
上同时阻止调用者阻塞的同时是如何一起进行的?
示例:
假设有一个窗体应用程序,其表单名为Form1
。处理两个事件:
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
事件并显示消息框。
答案 0 :(得分:2)
您可能会发现我的async
/await
post很有用。
正如其他人所说,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 **
}