如何取消FileStream.ReadAsync(..)请求
本文关键字:FileStream ReadAsync 请求 取消 何取消 | 更新日期: 2023-09-27 18:27:03
给定以下条件:
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace CancelAsyncFileReadFailure {
class Program {
static void Main( string[ ] args ) {
Console.WriteLine( Foo( ).Result );
Console.ReadLine( );
}
public static async Task<TaskStatus> Foo( ) {
byte[] bar = new byte[192000]; //Some arbitrarily significant number...
using ( FileStream FS = new FileSTream( @"Path/To/WarAndPeace.txt", FileMode.Open ) ){
CancellationTokenSource CTS = new CancellationTokenSource( );
Task T = FS.ReadAsync( bar, 0, 192000, CTS.Token );
CTS.Cancel( );
await T;
return T.Status;
}
}
T
将始终完成并返回RanToCompletion
。
我的用例有些复杂,因为我从一个可以随时打开或关闭的设备中读取(因此,我不是直接从文件中读取,而是从一个安全的文件句柄中读取;然而,在这种情况下和我的实际用例中,结果是相同的)。
我想中断(取消)FileStream。ReadToAsync()。
我怎么能这样做,让它停止阅读并立即取消?
好吧,最好在这里回答。
您需要使用FileOptions.Asynchronous
打开该文件。如果不这样做,FileStream
将不会实现真正的取消,并且只有在调用ReadAsync
时取消了令牌时才会返回已取消的Task
。
取消是最大的努力——只有当操作实际上能够被取消时,才会发生这种情况。
我在这里可以想到的两种情况是,要么它命中了文件系统缓存,在这种情况下,读取可以立即同步完成,要么I/O请求已经发送到磁盘。
Position
是什么?在FileStream
的情况下,可以将其回滚,但仅向前的流呢?如果您想在上一个任务转换到"已取消"状态后立即安排另一个ReadAsync
,该怎么办?你会得到一个丢失的数据块和一个可怕的损坏。对于微软来说,这似乎是一个明智的设计。缩小缓冲区大小并循环调用ReadAsync
,这样就可以获得所需的取消语义。