【问题标题】:.NET 4.5 Async + Await Fire and Forget potential memory leak?.NET 4.5 Async + Await Fire and Forget 潜在的内存泄漏?
【发布时间】:2014-08-12 09:15:19
【问题描述】:

我在 ASP.NET 中使用与下面类似的代码进行非关键的即发即弃操作

private void SomeMethod()
{
    FireAndForgetAsync();
}

private async Task FireAndForgetAsync()
{
    // Simulate medium running IO blocking operation
    await Task.Delay(sleepTime).ConfigureAwait(false);

    // Simulating the rare scenario where an error occurs
    throw new Exception("An Error Occurred");
}

在从异步方法返回的任务中捕获异常,这可以防止未处理的异常导致应用程序完全崩溃。

但是这段代码会导致内存泄漏吗?因为没有分配/访问返回的任务(及其异常)?我的想法是,除非某些 .NET 框架代码持有对任务的引用,否则它只会被垃圾收集。

【问题讨论】:

标签: c# .net asynchronous memory-leaks async-await


【解决方案1】:

您的代码没有内存泄漏的风险。至少来自您提供的 sn-p。

但是,由于未处理的异常,当任务完成时,CLR 可能会终止您的应用程序。

如果您创建了一个任务,并且您从未调用 task.Wait() 或尝试检索任务的结果,那么当垃圾收集器收集该任务时,它将在完成过程中关闭您的应用程序。有关详细信息,请参阅 Exception Handling in the TPL 上的 MSDN 页面。

(Reed Copsey's Answer)

对此有不止一种解决方案/解决方法。您可以在此 SOF 帖子中找到有关此内容的更多信息: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was

(正如I3arnon 提到的,这种行为在.Net 4.5 中有所改变。)

【讨论】:

  • 这种行为在 .net 4.5 中有所改变:Task Exception Handling in .NET 4.5
  • "为了让开发者更容易编写基于Tasks的异步代码,.NET 4.5 更改了未观察到的异常的默认异常行为。虽然未观察到的异常仍然会引发 UnobservedTaskException 事件(不做所以将是一个重大更改),默认情况下该进程不会崩溃“
  • @I3arnon 谢谢,我不知道! :)
  • 我还从 SO 评论中了解到这一点:stackoverflow.com/a/20025703/885318
【解决方案2】:

您的代码没有内存泄漏的危险。只要任务已经结束(它已经结束),就没有什么能阻止垃圾收集器收集它。如果您触发异常数量的这些任务,您可能会使用大量内存,但它们会被 GCed。

如果这些任务不会结束(例如,如果它们有 while (true))或者如果您保留对它们的引用,则有可能发生内存泄漏。


如 cmets 中所述。强烈建议不要使用“一劳永逸”和async-await

【讨论】:

    猜你喜欢
    • 2013-11-08
    • 2019-07-07
    • 2014-10-20
    • 1970-01-01
    • 2014-05-16
    • 2011-10-16
    • 1970-01-01
    • 2013-01-15
    • 1970-01-01
    相关资源
    最近更新 更多