如果一个任务在调用者线程上工作,它是如何工作的?

时间:2015-11-17 00:50:23

标签: c# multithreading asynchronous

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

示例

假设有一个窗体应用程序,其表单名为Form1。处理两个事件: 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事件并显示消息框。

1 个答案:

答案 0 :(得分:2)

您可能会发现我的async/await post很有用。

正如其他人所说,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 **
}