Is it a good idea to call await Task.Delay(0) to make an method "awaitable" in an ASP.NET Core app?

huangapple go评论62阅读模式
英文:

Is it a good idea to call await Task.Delay(0) to make an method "awaitable" in an ASP.NET Core app?

问题

以下是翻译好的部分:

我有以下接口和其两个实现:

public interface ITokenCache
{
    string GetToken(string key);
    string SetToken(string key, string value);
    void DeleteToken(string key);
}

public class InMemory : ITokenCache
{          
    // Implementation using IMemoryCache.
}

public class Redis : ITokenCache
{
    // Implemetation using Redis.
}

在使用`Microsoft.StackExchange.Redis`的API与Redis一起工作时,它们支持异步方法。但`IMemoryCache`不支持。因此,我可以使在`ITokenCache`中定义的方法“看起来可等待”,如下所示:

public async Task<string> GetToken(string key)
{
    return _memoryCache.Get(key) as string;
}

如果我选择这种方式,在`InMemory`实现中将会出现多个编译警告,因为我没有等待任何内容。在寻找解决方案时,有一个答案建议在`InMemory`实现中使用`await Task.Delay(0)`(它似乎只是用来抑制编译器警告的临时解决办法)。

但是,[文档][1]也建议不在ASP.NET Core Web应用程序中使用诸如`Task.Run`之类的方法。

满足我的要求的更好方式是什么?我应该忽略编译器警告吗?

[1]: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/best-practices?view=aspnetcore-7.0
英文:

I have the following interface and two of its implementations:

public interface ITokenCache
{
    string GetToken(string key);
    string SetToken(string key, string value);
    void DeleteToken(string key);
}

public class InMemory : ITokenCache
{          
    // Implementation using IMemoryCache.
}

public class Redis : ITokenCache
{
    // Implemetation using Redis.
}

I'm using APIs from Microsoft.StackExchange.Redis when working with redis and they support asynchronous methods. But IMemoryCache don't. Therefore, I can make the methods defined in ITokenCache "looking awaitable" such as,

public async Task&lt;string&gt; GetToken(string key)
{
    return _memoryCache.Get(key) as string;
}

If I choose this way, I get multiple compiler warnings as I await nothing in the InMemory implementation. When looking for a solution, one answer suggested using await Task.Delay(0) in the InMemory implementation. (It appeared as only a workaround to suppress compiler warning.)

But also, docs recommend not to use methods such as Task.Run in an ASP.NET Core Web Application.

What would be the better way to fulfill my requirement? Should I just ignore the compiler warnings?

答案1

得分: 3

在这种情况下的快速解决方法是await一个已经完成的任务,例如,await Task.CompletedTask;

然而,我更喜欢通过#pragma来抑制警告。这样可以使代码更加清晰:实际上这是一个同步实现异步方法(这正是警告所说的)。

基于Task.FromResult的方法的问题在于它们不能正确处理异常。在返回任务的方法中,期望是将异常放在返回的任务上。

英文:

The quick-fix in this situation is to await something that is already completed, e.g., await Task.CompletedTask;

However, I prefer just suppressing the warning with a #pragma. This gives the code more clarity: it is in fact a synchronous implementation of an asynchronous method (which is exactly what the warning is saying).

The problem with Task.FromResult-based approaches is that they do not properly handle exceptions. In a task-returning method, the expectation is that exceptions are placed on the returned task.

答案2

得分: 0

你可以在不标记async的情况下,通过返回一个包含你的值的Task.FromResult<TResult>来完成这个操作。这仍然会返回一个Task,因此你的方法可以被等待,但由于没有什么需要等待的内容,所以Task只是被标记为已完成。

对于你的void返回方法,如果你需要它可以被等待,你可以返回Task.CompletedTask

英文:

You can do this without marking async by returning a Task.FromResult<TResult> containing your value. This is a will still return a Task, so your method is awaitable, but as there's nothing to await the Task is simply marked as completed.

For your void return method, if you need it to be awaitable you can return Task.CompletedTask.

答案3

得分: 0

不需要在这里使用 await。您可以使用 Task.FromResult 并像这样返回它:

public Task<string> GetToken(string key)
{
    return Task.FromResult(_memoryCache.Get(key) as string);
}
英文:

There is no need in having an await here. You can just use Task.FromResult and return it here like this:

public Task&lt;string&gt; GetToken(string key)
{
    return Task.FromResult(_memoryCache.Get(key) as string);
}

huangapple
  • 本文由 发表于 2023年7月10日 21:56:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76654482.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定