我试图从使代码替换Thread
到Task
。睡眠/延迟只是代表长时间的活动。
static void Main(string[] args)
{
ThreadDoWork();
TaskDoWork();
}
public static void ThreadDoWork()
{
using (var dispose = new ThreadDispose())
{
dispose.RunAsync();
}
}
public static async void TaskDoWork()
{
using (var dispose = new TaskDispose())
{
await dispose.RunAsync();
}
}
public class ThreadDispose : IDisposable
{
public void RunAsync ()
{
ThreadPool.QueueUserWorkItem(state =>
{
Thread.Sleep(3000);
});
}
void IDisposable.Dispose()
{
File.AppendAllText("D:\\test.txt", "thread disposing");
}
}
public class TaskDispose : IDisposable
{
public async Task RunAsync()
{
await Task.Delay(3000);
}
void IDisposable.Dispose()
{
File.AppendAllText("D:\\test.txt", "task disposing");
}
}
test.txt
仅3秒后的结果
线程处理
我需要更改什么以使命令TaskDispose::Dispose
始终像执行一样ThreadDispose
?
让我们隔离每段代码:
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
,Task
并显式地Wait
:
public static async Task TaskDoWork()
{
using (var dispose = new TaskDispose())
{
await dispose.RunAsync();
}
}
现在:
static void Main(string[] args)
{
ThreadDoWork();
TaskDoWork().Wait();
}
边注:
有两个准则应遵循:
async void
是为了与事件处理程序兼容,因此很少在该范围之外的场合使用它。而是使用async Task
。
使用TAP(任务异步模式)执行异步操作的方法应以Async
后缀结尾。TaskDoWork
应该是TaskDoWorkAsync
。
使用Wait
上Task
可能会导致死锁。在此特定情况下,这不是因为控制台应用程序没有SynchronizationContext
并使用线程池。推荐的方法是“一直异步”并使用await
。
async-await标签wiki内有很多阅读材料,请务必检查一下。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句