在异步方法中不等待任务的注意事项 [英] Considerations for not awaiting a Task in an asynchronous method

查看:31
本文介绍了在异步方法中不等待任务的注意事项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个 Web API 项目,该项目使用 Azure 的托管缓存服务在内存中缓存数据库结果,以缩短响应时间并减少对数据库的重复流量.尝试将新项目放入缓存时,有时会抛出特定于缓存的异常,代码为 DataCacheErrorCode.RetryLater.自然地,为了稍后重试而无需阻塞此方法,我将 asyncawait Task.Delay 设置为稍后再试一次.以前,开发人员在其中硬编码了 Thread.Sleep,这确实会损害应用程序性能.

I'm working on a Web API project which uses Azure's managed cache service to cache database results in memory to improve response times and alleviate duplicate traffic to the database. When attempting to put a new item in the cache, occasionally a cache-specific exception will be thrown with a code of DataCacheErrorCode.RetryLater. Naturally, in order to retry later without needing to block on this method I made it async and await Task.Delay to try again a short time later. Previously a developer had hardcoded a Thread.Sleep in there that was really hurting application performance.

方法签名现在看起来与此类似:

The method signature looks something similar to this now:

public static async Task Put(string cacheKey, object obj)

在此更改之后,我从应用程序中调用以前同步版本的 Put 的所有其他地方收到了大约 75 个编译器警告,指示:

Following this change I get ~75 compiler warnings from all the other places in the application that called the formerly synchronous version of Put indicating:

由于不等待此调用,因此在调用完成之前会继续执行当前方法.考虑将await"运算符应用于调用结果.

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

在这种情况下,由于 Put 不返回任何内容,所以让这个操作 fire-and-forget 对我来说是有意义的,因为我没有看到任何阻止执行调用它的方法的原因.我只是想知道是否有任何危险或陷阱允许许多这些即发即弃的 Task 在后台运行,因为 Put 可以经常被调用.或者我应该等待,因为 99% 的时间我都不会收到重试错误并且 Task 几乎会立即完成.我只是想确保我不会因为线程过多(或类似的东西)而受到任何惩罚.

In this case, since Put doesn't return anything, it makes sense to me to let this operation fire-and-forget as I don't see any reason to block execution of the method that called it. I'm just wondering if there are any dangers or pitfalls for allowing a lot of these fire-and-forget Tasks running in the background as Put can be called quite often. Or should I await anyway since 99% of the time I won't get the retry error and the Task will finish almost immediately. I just want to make sure that I'm not incurring any penalties for having too many threads (or something like that).

推荐答案

如果有机会 Put 会因任何原因抛出任何其他异常,并且您不使用 await Put 每次您将对象插入缓存时,异常将被吞入返回的 Task 中,而该Task 不会被等待.如果您使用的是 .NET 4.0,则该异常将在该 Task. 的终结器中重新抛出.如果您使用 .NET 4.5,它将被简单地忽略(这可能是不可取的).

If there is a chance Put will throw any other exception for any kind of reason, and you don't use await Put each time you're inserting an object to the cache, the exceptions will be swallowed inside the returned Task which isn't being awaited. If you're on .NET 4.0, this exception will be re-thrown inside the Finalizer of that Task.. If you're using .NET 4.5, it will simply be ignored (and that might not be desirable).

想确保我不会因为太许多线程或类似的东西.

Want to make sure that I'm not incurring any penalties for having too many threads or something like that.

我只是为了把事情说清楚而已.当您使用 Task.Delay 时,您不会旋转任何新线程.Task 并不总是等于正在旋转的新线程.特别是这里,Task.Delay 在内部使用了一个 Timer,所以没有任何线程开销(除了当前被延迟的线程,如果你使用 等待).

Im just saying this to make things clear. When you use Task.Delay, you aren't spinning any new threads. A Task isn't always equal to a new thread being spun. Specifically here, Task.Delay internally uses a Timer, so there aren't any thread overheads (except for the thread which is currently being delayed if you do use await).

这篇关于在异步方法中不等待任务的注意事项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆