是等待来自同步源的方法等待Task.Run(()=>良好的做法?

我有一个方法,具有任务的async关键字。 此方法返回一个来自JwtSecurityTokenHandler().WriteToken(t);的字符串JwtSecurityTokenHandler().WriteToken(t); 事情是这个方法正文中的任务都没有等待。我得到警告CS-1998。 这表示你不应该使用async来完成同步方法。 但后来它补充说你可以使用await Task.Run(() => { 。所以这样做是好的做法吗?

 public async Task GenerateMyUserJwtToken(string email, IdentityUser user) //code that isnt awaitable { var u = await Task.Run(() => { return new JwtSecurityTokenHandler().WriteToken(token); }); return u; } 

编辑:我没有问我是什么错误,如果在没有等待分配的异步方法签名上实现await Task.Run(()是一个好主意。我还要求另一个异步方法在等待这个这里的另一种方法是代码

//等待方法:

 public async Task LoginAsync(LoginDto model) { return await GenerateMyUserJwtToken(model.Email, appUser); } //controller: [HttpPost("login")] public async Task Login([FromBody] LoginDto model) { var logMeIn = await new AuthUserService().LoginAsync(model); return logMeIn; //returns token } 

我的问题是这是异步还是完成任务。运行停止吗?

使用Task.Run只是为了使某些内容同步通常是一种不好的做法,但一般不能说明。

如果要执行的同步方法可能需要很长时间,那么它可以是一个解决方案。 请注意, Task.Run会将任务分配给池线程,并不总是需要。 常见的误解是异步方法总是使用或应该在async-await链的末尾某处使用线程。 但是,async-await 与线程无关 ,它与异步性(链​​接延迟任务)和创建线程只是创建等待任务的一个选项。

那有什么选择呢?

  1. 调用的方法很快,并且永远不会长时间阻塞调用者(> 100ms左右):根本不使用异步。 在这种情况下, Task.FromResult(result)是一个诱人的解决方案,但是非常不鼓励,因为它Task.FromResult(result)调用者带来误导。 仅在unit testing中使用它,或者如果您被迫实现接口的异步方法,则无法更改。

  2. 方法执行需要很长时间,因为它是CPU绑定的:现在你可以使用一个线程。 但是我通常不会将池线程用于持久的任务,因为如果线程池没有线程,它可能会导致令人讨厌的副作用。 使用await Task.Factory.StartNew(() => MyLongRunningTask(), cancellationToken, TaskCreationOptions.LongRunning); 相反,它创建了一个全新的线程,而不是打扰池。

  3. 方法执行需要很长时间,因为它是IO绑定的(例如,通过硬件发送/接收数据包):使用TaskCompletitionSource ,为设备的任何completition事件添加一个钩子(例如OS挂钩或IRQ通知)并从中设置completition源的结果并返回其任务。