假设我有这个功能:
void DoWork()
{
//do long work
}
我希望在不同的线程上执行此函数。 我习惯使用线程,因此在线程上执行它的一种方法是:
new Thread(DoWork).Start();
我正在尝试学习新的task/await
C#功能,因此我将方法修改为
async Task DoWork()
{
await Task.Run(delegate() { /*do stuff*/});
}
现在我可以这样使用它:
DoWork().Wait(0);
或者我可以再次修改方法:
async void DoWork()
{
await Task.Run(delegate() { /*do stuff*/});
}
现在请致电:
DoWork();
我应该使用哪种解决方案? 我不需要任务的结果也不需要等待它完成。
答案 0 :(得分:4)
答案都不是。您正在围绕同步逻辑创建一个简单的异步包装器。
Stephen Cleary:using Task.Run for asynchronous wrappers is a code smell
Stephen Toub(微软):Should I expose asynchronous wrappers for synchronous methods?(不,你不应该)。
DoWork
方法的异步部分不会添加任何值。它减少了你的API的价值,因为它不可能以任何方式执行你可能复杂的“do stuff”逻辑。
正确的做法是抛弃Task.Run
并将你的方法剥离到最基本的要点:
void DoWork()
{
// Do long CPU-bound work, synchronously
}
...
// Then, somewhere in the calling code:
Task.Run(() => DoWork()); // Fire and forget unless you await the resulting Task or block on it.
Task.Run
是当前调度线程池工作的首选方法(从.NET 4.6.x开始)