鉴于以下内容:
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()。
我怎样才能这样做,以至于它会停止阅读它的位置并立即取消?
答案 0 :(得分:3)
好的,这里更好的答案。
您需要使用FileOptions.Asynchronous
打开文件。如果不这样做,FileStream
将无法实现真正的取消,并且只有在调用Task
时取消令牌时才会返回已取消的ReadAsync
。
答案 1 :(得分:1)
取消是最好的努力 - 只有在实际上能够取消操作时才会发生。
我在这里可以想到的两种情况是要么点击文件系统缓存,在这种情况下,读取可以立即和同步完成,或者I / O请求已经发送到磁盘。
答案 2 :(得分:1)
威尔,科里以前的回答实际上是对的。取消需要在安全发生时进行。在流读取的情况下,唯一的这一点是之前读取实际开始。如果在流中取消流读取请求,那么当取消的任务实际完成时,您期望流的Position
是什么?在FileStream
的情况下将它回滚可能没问题,但是那些仅向前的流呢?如果要在上一个任务转换为“已取消”状态后立即安排另一个ReadAsync
,该怎么办?你得到一个丢弃的数据块和可怕的腐败。这实际上似乎是微软的一个明智的设计。缩小缓冲区大小并在循环中调用ReadAsync
- 然后您将获得所需的取消语义。