Biz*_*han 3 c# asynchronous stream
我正在写一个异步将单独的文本行写入文件的方法。如果取消,它将删除创建的文件并跳出循环。
这是简化的代码,可以正常工作。。。我标记了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;
}
Run Code Online (Sandbox Code Playgroud)
我打电话Close()就FileStream和StreamWriter我认为这将同步运行,并阻止该线程。我该如何改善?我不想等待它将缓冲区刷新到文件中,然后删除文件。
我想Dispose将调用该方法,而不是DisposeAsync在using范围的末尾。(此假设正确吗?)。
因此,请Dispose阻塞线程,以防止我先进行冲洗,FlushAsync以减少Dispose执行任务。(这在多大程度上是真的?)
我也可以删除using,而可以DisposeAsync在这两个地方手动编写。但这会降低可读性。
如果我打开FileStreamwith useAsync = true,它将DisposeAsync在using块结束时自动调用?
以上代码的任何解释或变型表现得更好的表示赞赏。
如您所愿,该using语句将调用Dispose(),而不是DisposeAsync()。
C#8带来了新的await using语法,但是由于某些原因,C#8.0的新增功能一文中未提及。
但这是在其他地方提到的。
await using var stream = new FileStream(filePath, FileMode.Create);
await using var writer = new StreamWriter(stream, Encoding.UTF8);
Run Code Online (Sandbox Code Playgroud)
但也请注意,这仅在以下情况下有效:
IAsyncDisposable最初引入的,或者Stream类型(FileStream,StreamWriter,等)使用它。即使在发布.NET Core 3.0的文章中,IAsyncDisposable也只是顺便提及而从未对其进行扩展。
另一方面,您不需要执行此操作(我现在知道为什么):
writer.Close();
stream.Close();
Run Code Online (Sandbox Code Playgroud)
此方法调用Dispose,指定
true释放所有资源。您不必专门调用Close方法。相反,请确保正确处理每个Stream对象。
由于您使用using,Dispose()(或DisposeAsync())将被自动调用,并且Close不会做任何尚未发生的事情。
因此,如果您确实需要专门关闭文件,但又想异步完成,则只需调用即可DisposeAsync()。它做同样的事情。
await writer.DisposeAsync();
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
77 次 |
| 最近记录: |