gpt4 book ai didi

c# - 在 C# 流上使用 DisposeAsync 的正确方法

转载 作者:行者123 更新时间:2023-11-30 14:21:14 25 4
gpt4 key购买 nike

我正在编写一种将单独的文本行异步写入文件的方法。如果它被取消,它会删除创建的文件并跳出循环。

这是工作正常的简化代码...我标记了 2 点,我不确定它们是如何处理的。我希望代码在任何情况下都不会阻塞线程。

public async Task<IErrorResult> WriteToFileAsync(string filePath,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();

using var stream = new FileStream(filePath, FileMode.Create);
using var writer = new StreamWriter(stream, Encoding.UTF8);

foreach (var line in Lines)
{
if (cancellationToken.IsCancellationRequested)
{
//
// [1] close, delete and throw if cancelled
//
writer.Close();
stream.Close();
if (File.Exists(filePath))
File.Delete(filePath);
throw new OperationCanceledException();
}

// write to the stream
await writer.WriteLineAsync(line.ToString());
}

//
// [2] flush and let them dispose
//
await writer.FlushAsync();
await stream.FlushAsync();
// await stream.DisposeAsync(); ??????
return null;
}

1

我正在 FileStreamStreamWriter 上调用 Close(),我认为它会同步运行并阻塞线程。我该如何改进呢?我不想等待它把缓冲区刷新到文件中,然后再删除文件。

2

我假设 Dispose 方法将在 using 范围的末尾被调用,而不是 DisposeAsync。 (这个假设是否正确?)。

所以 Dispose 会阻塞线程,为了防止我先用 FlushAsync 刷新,这样 Dispose 就会执行 东西。 (这在多大程度上是正确的?)

我还可以删除 using,而是可以在这两个地方手动编写 DisposeAsync。但它会降低可读性。

如果我使用 useAsync = true 打开 FileStream,它会在 using block 结束时自动调用 DisposeAsync 吗?


感谢任何对上述代码执行更好的解释或变体。

最佳答案

如您所见,using 语句将调用 Dispose(),而不是 DisposeAsync()

C# 8 带来了一个新的 await using 语法,但出于某种原因它没有在 What's new in C# 8.0 中提及。文章。

但它是 mentioned elsewhere .

await using var stream = new FileStream(filePath, FileMode.Create);
await using var writer = new StreamWriter(stream, Encoding.UTF8);

但还要注意,这仅在以下情况下有效:

  • 您正在使用 .NET Core 3.0+,因为那是 IAsyncDisposable被介绍,或者
  • 安装 Microsoft.Bcl.AsyncInterfaces NuGet 包。虽然这只是添加了接口(interface),并不包括使用它的 Stream 类型(FileStreamStreamWriter 等)的版本。

即使在 Announcing .NET Core 3.0文章中,IAsyncDisposable 只是顺便提及,从未展开。

另一方面, 你不需要这样做 (我现在明白为什么了):

writer.Close();
stream.Close();

the documentation for Close says:

This method calls Dispose, specifying true to release all resources. You do not have to specifically call the Close method. Instead, ensure that every Stream object is properly disposed.

由于您正在使用 usingDispose()(或 DisposeAsync())将被自动调用并Close 不会做任何尚未发生的事情。

因此,如果您确实需要专门关闭文件,但又想异步执行,只需调用 DisposeAsync() 即可。它做同样的事情。

await writer.DisposeAsync();

public async Task<IErrorResult> WriteToFileAsync(string filePath,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();

await using var stream = new FileStream(filePath, FileMode.Create);
await using var writer = new StreamWriter(stream, Encoding.UTF8);

foreach (var line in Lines)
{
if (cancellationToken.IsCancellationRequested)
{
// not possible to discard, FlushAsync is covered in DisposeAsync
await writer.DisposeAsync(); // use DisposeAsync instead of Close to not block

if (File.Exists(filePath))
File.Delete(filePath);
throw new OperationCanceledException();
}

// write to the stream
await writer.WriteLineAsync(line.ToString());
}

// FlushAsync is covered in DisposeAsync
return null;
}

关于c# - 在 C# 流上使用 DisposeAsync 的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58696427/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com