让我们隔离每段代码:
public static void ThreadDoWork()
{
using (var dispose = new ThreadDispose())
{
dispose.RunAsync();
}
}
public void RunAsync()
{
ThreadPool.QueueUserWorkItem(state =>
{
Thread.Sleep(3000);
});
}
您在第一段代码中所做的是在线程池线程上排队工作。因为您正在运行此代码using
范围并且它在不同的线程上异步运行,它处理立即地。这就是为什么您会在文本文件中看到处理消息。
public static async void TaskDoWork()
{
using (var dispose = new TaskDispose())
{
await dispose.RunAsync();
}
}
public class TaskDispose : IDisposable
{
public async Task RunAsync()
{
await Task.Delay(3000);
}
}
当你await
在你的方法中,你实际上所说的是:“执行这段代码。因为它本质上是异步的,所以我会将控制权返回给调用方法,请在完成异步操作后给我回电”.
你的代码命中了await
关键字并将控制权返回给您Main
方法。里面Main
,您的异步方法是最后一段要执行的代码,因此完成您的应用程序,并且不给您的机会Dispose
方法来执行。
如果您希望将其释放,则必须将返回类型更改为void
to Task
并明确地Wait
:
public static async Task TaskDoWork()
{
using (var dispose = new TaskDispose())
{
await dispose.RunAsync();
}
}
And now:
static void Main(string[] args)
{
ThreadDoWork();
TaskDoWork().Wait();
}
边注:
应遵循以下几条准则:
-
async void
是为了与事件处理程序兼容,很少有超出该范围的情况应该使用它。相反,使用async Task
.
-
使用 TAP(任务异步模式)执行异步操作的方法应以Async
后缀。TaskDoWork
应该TaskDoWorkAsync
.
-
Using Wait
on a Task
可能会导致死锁。在这种特殊情况下,它不会,因为控制台应用程序没有SynchronizationContext
并使用线程池。推荐的方法是“一路异步”并使用await
.
里面有很棒的阅读材料异步等待标签维基 https://stackoverflow.com/tags/async-await/info, 一定要检查一下。