【发布时间】:2019-12-18 18:34:43
【问题描述】:
以下两个结果都导致 for 循环在它自己的线程上运行。在 for 循环完成之前,它们都不会被标记为完成。
class Program
{
static async Task SomethingAsync()
{
await Task.Run(() =>
{
for (int i = 0; i < 100; i++)
Console.WriteLine("s11{0} {1}", i, Thread.CurrentThread.ManagedThreadId);
}
);
}
static async Task SomethingAsync2()
{
await Task.Delay(1);
for (int i = 0; i < 100; i++)
Console.WriteLine("s22{0} {1}", i, Thread.CurrentThread.ManagedThreadId);
}
static void Main(string[] args)
{
var t1 = SomethingAsync();
var t2 = SomethingAsync2();
for (int i = 0; i < 300; i++)
Console.WriteLine("m{0} {1} {2} {3}", i, Thread.CurrentThread.ManagedThreadId,t1.IsCompleted,t2.IsCompleted);
}
}
有什么功能上的区别吗? (除了明显的延迟)
在 SomethingAsync2() 的情况下,Task.Delay 是我错误地发现的。 await 可以调用任何返回 GetAwaiter 的方法吗?
【问题讨论】:
-
您是只对控制台应用程序感兴趣,还是对 Windows 窗体也感兴趣?
-
在本例中它是一个控制台应用程序和一个学习实验。我曾预计Something2() 方法最终会回到MainThread。我想看看它是如何阻止它的,但令人惊讶的是它最终出现在一个备用的 WorkerPool 线程上。但是,如果我能在 Forms 中得到不同的结果,那就很好理解了。
-
是的,如果进程有一个 Windows 消息队列(即它是一个 GUI 应用程序),那么
await Task.Delay()之后的继续将被编组到正在处理消息队列的 UI 线程上(假设 @ 987654323@ 是从 UI 线程调用的)。如果进程没有消息队列(例如控制台应用程序)或未从 UI 线程调用Task.Delay(),则线程池中的线程将用于继续。 -
await Task.Run几乎总是一个错误。Task.Run- “请找一些其他线程来运行这段代码,我还有其他工作要做”。await- “好吧,在其他工作完成之前,我没有什么有用的工作要做” -
@Damien_The_Unbeliever 如果你想在后台调用一个长时间运行的方法并在它返回时更新 UI 怎么办?在这种情况下使用
await和Task.Run()可以避免在后台任务完成后调用Control.Invoke()来更新UI。
标签: c# async-await task