【问题标题】:How do I get the "await using" syntax correct?如何正确使用“等待使用”语法?
【发布时间】:2022-01-28 08:53:22
【问题描述】:

我有以下同步代码,运行良好:

    private void GenerateExportOutput()
    {
        using StreamWriter writer = new(Coordinator.OutputDirectory + @"\export.txt");

        if (this.WikiPagesToExport.IsEmpty)
        {
            return;
        }

        var wanted = new SortedDictionary<string, WikiPage>(this.WikiPagesToExport, StringComparer.Ordinal);
        foreach (var title in wanted.Keys)
        {
            writer.WriteLine(title);
        }
    }

我想把它改成异步的。所以:

    private async Task GenerateExportOutputAsync()
    {
        using StreamWriter writer = new(Coordinator.OutputDirectory + @"\export.txt");

        if (this.WikiPagesToExport.IsEmpty)
        {
            return;
        }

        var wanted = new SortedDictionary<string, WikiPage>(this.WikiPagesToExport, StringComparer.Ordinal);
        foreach (var title in wanted.Keys)
        {
            await writer.WriteLineAsync(title).ConfigureAwait(false);
        }

        await writer.FlushAsync().ConfigureAwait(false);
    }

编译。但是我使用的一种分析器 (Meziantou.Analyzer) 现在建议我“更喜欢使用 'await using'”。我从来没有使用过 await using (尽管我过去尝试过几次并且总是遇到我现在遇到的相同问题)。但我想用它,所以:

        await using StreamWriter writer = new StreamWriter(OutputDirectory + @"\export.txt").ConfigureAwait(false);

现在它不再编译:CS0029 Cannot implicitly convert type 'System.Runtime.CompilerServices.ConfiguredAsyncDisposable' to 'System.IO.StreamWriter'。好的,好的,所以我改用var

        await using var writer = new StreamWriter(OutputDirectory + @"\export.txt").ConfigureAwait(false);

它通过了 CS0029,但现在后面的代码无法编译:Error CS1061 'ConfiguredAsyncDisposable' does not contain a definition for 'WriteLineAsync'FlushAsync 也有类似的代码。Soooo...也许可以转换它?

            await ((StreamWriter)writer).WriteLineAsync(title).ConfigureAwait(false);

没有:Error CS0030 Cannot convert type 'System.Runtime.CompilerServices.ConfiguredAsyncDisposable' to 'System.IO.StreamWriter'

我现在和过去几次在谷歌上搜索并阅读了一堆,但我完全无法弄清楚如何使用这个“等待使用”的东西。我该怎么做?谢谢。

【问题讨论】:

  • @madreflection,谢谢!
  • @Charles:这可能有效(因为没有抛出异常),但它不会在流对象上调用IAsyncDisposable.Dispose。它将改用IDisposable.Dispose
  • @Charles:当然,除非你不能直接使用ConfigureAwait(false),这是这个问题的症结所在。我链接的页面显示await using (_variable_.ConfigureAwait(false)) 将某些内容分配给_variable_。该变量具有正确的类型,而await using 单独捕获用于异步处理的已配置等待对象。

标签: c# .net asynchronous async-await iasyncdisposable


【解决方案1】:

目前的await using 语法(C# 10)还有很多不足之处,它支持配置IAsyncDisposables 的等待。我们能做的最好的就是:

private async Task GenerateExportOutputAsync()
{
    StreamWriter writer = new(Coordinator.OutputDirectory + @"\export.txt");
    await using (writer.ConfigureAwait(false))
    {
        //...
    }
}

...这并不比完全不使用await using 语法更紧凑:

private async Task GenerateExportOutputAsync()
{
    StreamWriter writer = new(Coordinator.OutputDirectory + @"\export.txt");
    try
    {
        //...
    }
    finally { await writer.DisposeAsync().ConfigureAwait(false); }
}

相关 GitHub 问题:Using ConfigureAwait in "await using" declaration

【讨论】:

    猜你喜欢
    • 2019-03-03
    • 2018-02-04
    • 2020-09-10
    • 2019-08-27
    • 1970-01-01
    • 2018-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多