1

鉴于以下情况:

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

我怎样才能做到这一点,它会停止阅读它所在的位置并立即取消?

4

3 回答 3

3

好吧,在这里更好的回答。

您需要使用FileOptions.Asynchronous. 如果你不这样做,FileStream将不会实现真正的取消,并且只会Task在调用时取消令牌时返回取消ReadAsync

于 2015-12-17T01:35:29.970 回答
1

取消是尽力而为——只有当一个操作实际上能够被取消时才会发生。

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

于 2015-12-17T01:27:45.700 回答
1

威尔,科里之前的回答实际上是对的。取消需要在安全的情况下进行。在流读取的情况下,唯一的这样的点是读取实际开始之前。Position如果一个流读取请求在运行中被取消,当被取消的任务实际完成时,你期望流是什么?在 的情况下回滚它可能很好FileStream,但是只转发的流呢?如果您想ReadAsync在前一个任务转换为 Canceled 状态后立即安排另一个任务怎么办?你会得到一个丢弃的数据块和一个可怕的损坏。这实际上似乎是微软的一个明智的设计。使您的缓冲区大小更小并调用ReadAsync在一个循环中-然后您将获得所需的取消语义。

于 2015-12-17T01:40:38.907 回答