Как отменить запрос FileStream.ReadAsync( ...)?
Учитывая следующее:
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 ответа
Хорошо, лучше ответь здесь.
Вам нужно открыть файл с FileOptions.Asynchronous
, Если нет, FileStream
не будет осуществлять истинную отмену и будет возвращать только отмененную Task
если токен был отменен во время вызова ReadAsync
,
Отмена - лучшее усилие - это происходит, только если операция действительно может быть отменена.
Здесь я могу вспомнить два случая: либо попадание в кеш файловой системы, в этом случае чтение может быть завершено немедленно и синхронно, либо запрос ввода-вывода уже отправлен на диск.
Уилл, предыдущий ответ Кори на самом деле был прав на деньги. Отмена должна произойти, когда это безопасно. В случае чтения потока единственной такой точкой является перед началом чтения. Если запрос на чтение потока отменен во время полета, что вы ожидаете от потока Position
быть, когда отмененная задача действительно завершается? Это может быть хорошо, чтобы откатить его в случае FileStream
, а как насчет потоков, которые предназначены только для пересылки? Что делать, если вы хотите запланировать другое ReadAsync
сразу после перехода предыдущей задачи в отмененное состояние? Вы получите потерянный кусок данных и ужасную коррупцию. На самом деле это похоже на разумный дизайн со стороны Microsoft. Уменьшите размер буфера и вызовите ReadAsync
в цикле - тогда вы получите желаемую семантику отмены.