首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在异步方法中不等待任务的注意事项

在异步方法中不等待任务的注意事项
EN

Stack Overflow用户
提问于 2014-11-17 17:28:34
回答 4查看 6.9K关注 0票数 13

我正在开发一个Web项目,该项目使用Azure的托管缓存服务来缓存数据库,从而产生内存,以提高响应时间,并减少对数据库的重复通信。当试图将新项放入缓存中时,偶尔会使用DataCacheErrorCode.RetryLater代码引发特定于缓存的异常。当然,为了稍后重试而不需要阻止这个方法,我让asyncawait Task.Delay在短时间后再试一次。以前,开发人员在其中硬编码了一个Thread.Sleep,这确实损害了应用程序的性能。

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

代码语言:javascript
复制
public static async Task Put(string cacheKey, object obj)

在进行此更改后,我从应用程序中调用以前同步版本的Put的所有其他地方得到~75条编译器警告,指示:

由于没有等待此调用,因此在调用完成之前,将继续执行当前方法。考虑将“等待”操作符应用于呼叫的结果。

在这种情况下,由于fire-and-forget不返回任何内容,所以让这个操作执行Put是有意义的,因为我没有看到任何理由阻止调用它的方法的执行。我只是想知道是否有任何危险或陷阱允许很多这样的火灾和忘记Task在后台运行,因为Put可以经常被调用。或者我是否应该等待,因为99%的时间我不会得到重试错误和Task将几乎立即完成。我只想确保我不会因为线程太多而招致任何惩罚(或者类似的事情)。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-11-17 17:36:18

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

希望确保我不会因为线程太多或诸如此类的事情而招致任何惩罚。

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

票数 10
EN

Stack Overflow用户

发布于 2014-11-17 17:31:03

警告是告诉你,在一个你可能不想开火和忘记的地方,你会着火,忘记自己的行为。如果您确实想要触发和忘记,并且在不知道操作何时完成或操作是否成功完成的情况下就不会有问题继续进行,那么您可以安全地忽略警告。

票数 3
EN

Stack Overflow用户

发布于 2017-05-09 08:35:35

释放一个任务来运行的一个负面结果是编译器警告本身--75个编译器警告本身就是一个问题,它们隐藏真实的警告。

如果您想向编译器发出信号,表示您没有对任务的结果做任何事情,那么您可以使用一个简单的扩展方法,它什么也不做,但是满足了编译器对明确性的要求。

代码语言:javascript
复制
// Do nothing.
public static void Release(this Task task)
{
}

现在你可以打电话了

代码语言:javascript
复制
UpdateCacheAsync(data).Release();

没有任何编译器警告。

https://gist.github.com/lisardggY/396aaca7b70da1bbc4d1640e262e990a

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26978366

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档