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

时间:2015-12-17 01:09:37

标签: c# asynchronous async-await filestream cancellationtokensource

鉴于以下内容:

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()。

我怎样才能这样做,以至于它会停止阅读它的位置并立即取消?

3 个答案:

答案 0 :(得分:3)

好的,这里更好的答案。

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

答案 1 :(得分:1)

取消是最好的努力 - 只有在实际上能够取消操作时才会发生。

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

答案 2 :(得分:1)

威尔,科里以前的回答实际上是对的。取消需要在安全发生时进行。在流读取的情况下,唯一的这一点是之前读取实际开始。如果在流中取消流读取请求,那么当取消的任务实际完成时,您期望流的Position是什么?在FileStream的情况下将它回滚可能没问题,但是那些仅向前的流呢?如果要在上一个任务转换为“已取消”状态后立即安排另一个ReadAsync,该怎么办?你得到一个丢弃的数据块和可怕的腐败。这实际上似乎是微软的一个明智的设计。缩小缓冲区大小并在循环中调用ReadAsync - 然后您将获得所需的取消语义。