Task.Run(job) 和 job() 有什么不同;等待 Task.CompleteTask?

Pan*_*nic 0 .net c# async-await .net-core

我想使同步功能异步

public JobSync()
{
 // a lot of logic
}
Run Code Online (Sandbox Code Playgroud)

两个都

public async JobAsync()
{
 JobSync()
 await Task.CompleteTask;
}
Run Code Online (Sandbox Code Playgroud)

Task.Run(()=>JobSync())
Run Code Online (Sandbox Code Playgroud)

作品,

但是两种方式有什么区别吗?

Joh*_*lay 7

我想使同步功能异步

这个版本根本不是异步的:

public async Task JobAsync()
{
    JobSync()
    await Task.CompleteTask;
}
Run Code Online (Sandbox Code Playgroud)

它将完全同步运行,您只需通过async关键字添加不必要的开销。

这个版本是“假异步”:

Task.Run(()=>JobSync())
Run Code Online (Sandbox Code Playgroud)

Task.Run只需在线程池上运行同步代码。但是,它确实会TaskJobSync运行之前返回 a ,如果您的目标是 UI 应用程序,这会很有用,因为 UI 线程在JobSync运行时会被释放。

这里真正的问题是你为什么想要JobSync异步,答案是你不应该。

当该方法涉及 I/O 时,异步就派上用场了,因为可以在等待响应的同时释放线程来处理其他工作。

如果JobSync是一个昂贵的 CPU 绑定方法冻结了您的 UI,只需使用Task.Run以下命令调用它:

await Task.Run(JobSync);
Run Code Online (Sandbox Code Playgroud)

根据评论更新

如果您的目标是需要Task返回方法的 API ,例如BackgroundService.ExecuteAsync,那么Task.FromResult最有效的解决方法是:

public override Task ExecuteAsync(CancellationToken ct)
{
    return Task.FromResult(JobSync());
}
Run Code Online (Sandbox Code Playgroud)

这只是敲击的结果的JobSync()在一个Task目的是满足的要求ExecuteAsync,但不强制代码对线程池不必要地运行。