C# 当任务在调用线程上时,它是如何工作的?
正如我们所知,运行一个新的C# 当任务在调用线程上时,它是如何工作的?,c#,multithreading,asynchronous,C#,Multithreading,Asynchronous,正如我们所知,运行一个新的任务并不能保证生成一个新线程。我想知道两块代码(任务调用者的剩余代码和任务)如何在同一线程上同时阻止调用者阻塞 示例: 假设有一个windows窗体应用程序,其窗体名为Form1。处理两个事件: 按键,点击 this.KeyPreview = true; ... private void Form1_Click(object sender, EventArgs e) { Messag
任务
并不能保证生成一个新线程。我想知道两块代码(任务调用者的剩余代码和任务)如何在同一线程上同时阻止调用者阻塞
示例:
假设有一个windows窗体应用程序,其窗体名为Form1
。处理两个事件:
按键
,点击
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)
;
});
}
this.KeyPreview=true;
...
私有void Form1\u单击(对象发送方,事件参数e)
{
MessageBox.Show(“单击”);
}
私有异步void Form1\u KeyPress(对象发送方,KeyPressEventArgs e)
{
Console.WriteLine(“调用程序threadId=“+Thread.CurrentThread.ManagedThreadId”);
等待任务。运行(()=>
{
var start=DateTime.Now;
WriteLine(“在线程上异步工作:+thread.CurrentThread.ManagedThreadId”);
while((DateTime.Now-start).TotalSeconds<5)
;
});
}
如果我按下一个键,持续5秒钟,控制台中就会有东西被写入。同时,表单可以处理单击事件并显示消息框。您可能会发现我的方法很有用
正如其他人所指出的,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 **
}
请注意,导致指定代码在线程池线程上运行的是任务。运行-而不是等待
如果使用纯异步
/等待
而不使用任务。运行
,您将看到所有代码都在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 **
}
@阿列克谢列文科夫:是的。@Hans,你的假设是错误的<代码>任务。运行
正文保证在另一个线程上运行。它不需要是“新”线程,但仍然是“另一个”。或者在非常罕见的情况下(不是在你的情况下),即使是相同的,但以后。简而言之,Task.Run
与async
方法无关-它所做的只是“将要在线程池上运行的指定工作排队,并返回表示该工作的任务对象”-请参阅。是的,您可以-如果您只是通过等待其他异步方法来使用它们。我建议您阅读Stephen Toub的博客(从Ron Beyer提供的链接开始),以及“async
方法可以在当前线程上运行”——是的,但是以task.run()开始的任务不能运行(正如Ivan所说)。“您能在没有Task.Run()
的情况下编写async
方法吗?”--绝对可以。我甚至猜想大多数async
都没有使用Task.Run()
。一个非常常见的异步场景是I/O,在当前线程上运行的async
I/O方法调用的一个示例是,如果I/O可以立即完成(例如,操作系统缓冲区已经准备好了要返回的数据)。方法本身中的代码可能会在当前线程中运行(取决于代码在方法中的位置以及当前同步上下文是什么);但是当它在等待其他东西时,它根本就没有运行,不管是在当前线程中还是在其他线程中。