当任务在调用线程上时,它是如何工作的

本文关键字:何工作 工作 调用 任务 线程 | 更新日期: 2023-09-27 18:22:06

正如我们所知,运行一个新的Task并不能保证生成一个新线程。我想知道两块代码(任务调用者和任务的剩余代码)如何在同一个thread上同时阻止调用者阻塞?

示例

假设有一个窗体为Form1的windows窗体应用程序。处理两个事件:KeyPressClick

        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帖子很有用。

正如其他人所指出的,asyncawait本身并不意味着多线程。但是,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 **
}