我正在开发一个Web项目,该项目使用Azure的托管缓存服务来缓存数据库,从而产生内存,以提高响应时间,并减少对数据库的重复通信。当试图将新项放入缓存中时,偶尔会使用DataCacheErrorCode.RetryLater代码引发特定于缓存的异常。当然,为了稍后重试而不需要阻止这个方法,我让async和await Task.Delay在短时间后再试一次。以前,开发人员在其中硬编码了一个Thread.Sleep,这确实损害了应用程序的性能。
方法签名现在看起来与此类似:
public static async Task Put(string cacheKey, object obj)在进行此更改后,我从应用程序中调用以前同步版本的Put的所有其他地方得到~75条编译器警告,指示:
由于没有等待此调用,因此在调用完成之前,将继续执行当前方法。考虑将“等待”操作符应用于呼叫的结果。
在这种情况下,由于fire-and-forget不返回任何内容,所以让这个操作执行Put是有意义的,因为我没有看到任何理由阻止调用它的方法的执行。我只是想知道是否有任何危险或陷阱允许很多这样的火灾和忘记Task在后台运行,因为Put可以经常被调用。或者我是否应该等待,因为99%的时间我不会得到重试错误和Task将几乎立即完成。我只想确保我不会因为线程太多而招致任何惩罚(或者类似的事情)。
发布于 2014-11-17 17:36:18
如果由于任何原因,Put有可能抛出任何其他异常,而且每次向缓存中插入对象时都不使用await Put,则异常将在未等待的返回的Task中被吞没。如果您使用的是.NET 4.0,此异常将在该Task.的终结器中重新抛出。如果您使用的是.NET 4.5,它将被忽略(这可能是不可取的)。
希望确保我不会因为线程太多或诸如此类的事情而招致任何惩罚。
我这么说只是想说清楚。当您使用Task.Delay时,您不会旋转任何新线程。Task并不总是等于正在旋转的新线程。特别是在这里,Task.Delay在内部使用一个Timer,所以没有任何线程开销(除了当前正在被延迟的线程,如果您使用await)。
发布于 2014-11-17 17:31:03
警告是告诉你,在一个你可能不想开火和忘记的地方,你会着火,忘记自己的行为。如果您确实想要触发和忘记,并且在不知道操作何时完成或操作是否成功完成的情况下就不会有问题继续进行,那么您可以安全地忽略警告。
发布于 2017-05-09 08:35:35
释放一个任务来运行的一个负面结果是编译器警告本身--75个编译器警告本身就是一个问题,它们隐藏真实的警告。
如果您想向编译器发出信号,表示您没有对任务的结果做任何事情,那么您可以使用一个简单的扩展方法,它什么也不做,但是满足了编译器对明确性的要求。
// Do nothing.
public static void Release(this Task task)
{
}现在你可以打电话了
UpdateCacheAsync(data).Release();没有任何编译器警告。
https://gist.github.com/lisardggY/396aaca7b70da1bbc4d1640e262e990a
https://stackoverflow.com/questions/26978366
复制相似问题