我有一个带有任务的async关键字的方法。这个方法返回一个来自JwtSecurityTokenHandler().WriteToken(t);
的字符串。事情是方法正文中的任何一个都没有等待。我得到警告CS-1998。这表示你不应该使用async来完成同步方法。但随后它补充说你可以使用await Task.Run(() => {
。这样做是好的做法吗?
public async Task<object> 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<object> LoginAsync(LoginDto model)
{
return await GenerateMyUserJwtToken(model.Email, appUser);
}
//controller:
[HttpPost("login")]
public async Task<object> Login([FromBody] LoginDto model)
{
var logMeIn = await new AuthUserService().LoginAsync(model);
return logMeIn; //returns token
}
我的问题是这一直是异步还是任务。运行是否停止了这个过程?
答案 0 :(得分:3)
仅使用Task.Run
进行同步通常是一种不好的做法,但通常无法说明。
如果要执行的同步方法可能需要很长时间,那么可以解决方案。请注意,Task.Run
会将任务分配给池线程,并不总是需要。常见的误解是异步方法总是使用或应该在async-await链的末尾某处使用线程。但是,async-await有nothing to do with threads,它是关于异步(链接延迟任务)和创建线程只是创建等待任务的一个选项。
那么有什么选择?
要调用的方法很快,并且永远不会长时间阻止调用方(> 100ms左右):根本不要使用异步。在这种情况下,Task<T>.FromResult(result)
是一个诱人的解决方案,但非常气馁,因为它会给调用者带来误导。仅在单元测试中使用它,或者如果您被迫实现接口的异步方法,则无法更改。
方法执行需要很长时间,因为它是CPU绑定的:现在你可以使用一个线程。但我通常不会将池线程用于持久的任务,因为如果线程池没有线程,它可能会导致令人讨厌的副作用。请改用await Task.Factory.StartNew(() => MyLongRunningTask(), cancellationToken, TaskCreationOptions.LongRunning);
,这会创建一个全新的线程,而不是打扰池。
方法执行需要很长时间,因为它是IO绑定的(例如,通过硬件发送/接收数据包):使用TaskCompletitionSource<T>
,为设备的任何completition事件添加一个钩子(例如,OS挂钩或IRQ通知)并从中设置完成源的结果并返回其任务。