如何取消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()。

我怎么能这样做,让它停止阅读并立即取消?

如何取消FileStream.ReadAsync(..)请求

好吧,最好在这里回答。

您需要使用FileOptions.Asynchronous打开该文件。如果不这样做,FileStream将不会实现真正的取消,并且只有在调用ReadAsync时取消了令牌时才会返回已取消的Task

取消是最大的努力——只有当操作实际上能够被取消时,才会发生这种情况。

我在这里可以想到的两种情况是,要么它命中了文件系统缓存,在这种情况下,读取可以立即同步完成,要么I/O请求已经发送到磁盘。

Will,Cory之前的回答实际上是对的。取消需要在安全的情况下进行。在流读取的情况下,唯一这样的点是读取实际开始之前的。如果流读取请求在飞行中被取消,那么当被取消的任务实际完成时,您希望流的Position是什么?在FileStream的情况下,可以将其回滚,但仅向前的流呢?如果您想在上一个任务转换到"已取消"状态后立即安排另一个ReadAsync,该怎么办?你会得到一个丢失的数据块和一个可怕的损坏。对于微软来说,这似乎是一个明智的设计。缩小缓冲区大小并循环调用ReadAsync,这样就可以获得所需的取消语义。