【问题标题】:Will using await on Task.Run casue "access to disposed closure" error?在 Task.Run 上使用 await 会导致“访问已处置的闭包”错误吗?
【发布时间】:2018-08-28 09:22:38
【问题描述】:

代码示例

public async Task HeavyTask()
{
  using(var res = new BigResource())
  {
    await Task.Run(() => service.Do(res));
  }
}

我有一些类似于上面的代码,ReSharper 在使用 res 实例时警告我“访问已处置的闭包”。

如果我不使用await 关键字,我知道res 实例可能service 尝试访问它时被释放。

但我认为如果我使用await 关键字,执行HeavyTask 方法的线程将在Task.Run 完成之前不会继续,并且应该没有访问已处置闭包的风险。

请帮助我了解我哪里出错了,以及解决此问题的首选模式是什么。

【问题讨论】:

    标签: c# async-await resharper


    【解决方案1】:

    你不会错的。这不会在处理后访问res。问题只是 ReSharper 不知道这一点。 Task.Run 可以存储委托以便稍后执行。你知道它不这样做的唯一方法是因为你知道Task.Run 做了什么。 ReSharper 没有。

    【讨论】:

    • 虽然我可以理解 Resharper 对所有其他函数调用的行为,但知道 Task.Run 的作用并不是特例,这有点可悲:/
    • @poke 我同意,但想补充一点,BCL 有 很多 更多的方法,这些方法的使用与使用相同的方法应该得到相同的特殊情况.
    • 这与 Task.Run 无关,而是与将用于生成完全不同的代码(所谓的异步状态机)的异步方法有关。所以 Resharper 不仅仅知道结果代码。
    • @DmytroMukalov 这不是真的,您可以通过查看是否为 lambda 未捕获的变量生成警告来轻松检查这一点。
    • @hvd 我不确定到底是不是真的?
    猜你喜欢
    • 1970-01-01
    • 2013-10-02
    • 2020-07-21
    • 1970-01-01
    • 2017-06-16
    • 1970-01-01
    • 2017-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多