【问题标题】:Async within using in C# 6.0在 C# 6.0 中使用异步
【发布时间】:2017-04-16 03:47:20
【问题描述】:

我正在“VisualStudio 2017”、“C# 6.0”、“R#”上开发应用程序。在C# 6.0 中引入了新功能 - 支持async/await' withintry/cath'。我使用 using 运算符(实际上是 try/finaly 在引擎盖下),但我仍然收到警告 Access to disposed closure。但真的 msGet 不应该在DownloadToStreamAsync 之前被释放。

  • 它真的可以访问已处置的变量吗?
  • R#故障吗?

我的代码:

using( var msGet = new MemoryStream() )
{
    var stopwatchAp = Stopwatch.StartNew();
    var stopwatchPureDownload = new Stopwatch();
    var times = new long[ 201 ];
    var retryCount = -1;
    await this._ap.Do( () =>
    {
        stopwatchPureDownload.Restart();
        var downloadToStreamAsync = blob.DownloadToStreamAsync( msGet );
        downloadToStreamAsync.ContinueWith( t => times[ ++retryCount ] = stopwatchPureDownload.ElapsedMilliseconds );
        return downloadToStreamAsync;
    } ).ConfigureAwait( false );
}

更新 1 我之前也看到过类似的问题:

Access to disposed closure in C#? (但这里的例子不包含await,它不是关于'async/await')

Calling asynchronous method in using statement 。 (答案说 - 使用await。但你可以看到我的代码包含await - 但我仍然有警告)

这些问题也可以追溯到 2013 年。 2013 年没有 C# 6.0。这就是我问的原因。

【问题讨论】:

  • 请发布代码而不是图片,这是一种不好的做法
  • @Alex 可以在 try 块内等待,但不能在 catch 或 finally 块内等待(在 C# 6 之前)。所以这与这个问题并不真正相关。
  • 至于问题 - Resharper 不够聪明,无法识别捕获的 msSet 在异步块运行时不会被释放。它只是看到您捕获并使用了一些后来被释放的变量(根本与异步无关)。
  • 原始帖子的日期无关紧要。情况是一样的。该语言没有引入像这样的重大更改
  • 此外 - Do 做什么?谁说它在返回之前执行 lambda before?无法保证msGet 在代码实际执行时可用。 Do 可能会存储它以供以后执行。

标签: c# visual-studio async-await visual-studio-2017 c#-6.0


【解决方案1】:

您的Do 方法采用Func<Task>,在您提供此的调用中,您包含对msGet 的引用,这是一个闭包,编译器会将其转换为可从您的@ 访问的字段987654324@.

Resharper 无法确定您对 Func<Task> 的使用是否在 using 块的范围或生命周期内,例如,您可以在 Do 方法中,将 func 复制到字段中并再次调用它稍后。

如果您在Do 内立即执行Func<Task>,您可以放心地忽略警告:

// ReSharper disable once AccessToDisposedClosure

【讨论】:

  • 谢谢 =) 很高兴我能帮上忙。如果此答案已解决您的问题,请随时将此答案标记为已接受。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-29
  • 1970-01-01
  • 2018-02-20
  • 2010-09-07
  • 2021-06-12
相关资源
最近更新 更多