1

Учитывая следующее:Как отменить запрос 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().

Как я могу сделать это так, чтобы он прекратил читать, где он находится, и отменил его прямо сейчас?

+1

'CancellationTokenSource' необходимо настроить вне функции, [проверить это] (https://msdn.microsoft.com/en-us/library/jj155759.aspx) – balexandre

+0

@balexandre: Пожалуйста, уточните. Вы имеете в виду, что мне нужно объявить его вне функции (как переменную класса) или что мне нужно вызвать 'CancellationTokenSource.Token.Register (() => {})' что-то? – Will

+2

Я не вижу неправильного использования 'CancellationTokenSource' здесь. –

ответ

3

Хорошо, лучше ответьте здесь.

Вам необходимо открыть файл с помощью FileOptions.Asynchronous. Если вы этого не сделаете, FileStream не будет осуществлять истинное аннулирование и вернет только отмененный Task, если токен был отменен во время звонка ReadAsync.

+0

Закрыть, но не сигары. Это то, что я изначально думал (поскольку конструктор, используемый в вопросе, создает «FileStream» с «IsAsync = false»), но поведение остается точно таким же. –

+0

Спасибо, хотя. К сожалению, при открытии с помощью 'SafeFileHandle' перегрузки нет, что позволяет мне передавать' FileOptions.Asynchronous' ... – Will

+0

@ Будет, есть конструктор 'FileStream' с параметром' isAsync', который будет делать то же самое. –

1

Отмена - лучшее усилие - это происходит только в том случае, если операция действительно может быть отменена.

Два случая, о которых я могу думать, либо попадают в кэш файловой системы, и в этом случае чтение может быть выполнено немедленно и синхронно или что запрос ввода-вывода уже отправлен на диск.

+0

Итак, вкратце - FileStream.ReadAsync() фактически не реализует аннулирование, по крайней мере, в моем случае использования. *здорово*. – Will

1

Будет, предыдущий ответ Кори был фактически прав на деньги. Аннулирование должно произойти, когда это безопасно, чтобы это произошло. В случае чтения потока единственной такой точкой является до чтение начинается. Если запрос на чтение потока отменяется во время полета, что вы ожидаете от потока Position, когда завершена отмененная задача? Было бы неплохо отбросить его обратно в случае FileStream, но как насчет потоков, которые доступны только вперед? Что делать, если вы хотите запланировать еще один ReadAsync сразу же после перехода предыдущих задач в состояние «Отменено»? Вы получите упавший фрагмент данных и ужасную коррупцию. На самом деле это кажется разумным дизайном со стороны Microsoft. Уменьшите размер буфера и вызовите ReadAsync в цикле - тогда вы получите желаемую семантику отмены.

+0

Спасибо. Это сработало бы, если бы я читал огромное количество данных, но, к сожалению, то, что я читаю, на самом деле довольно мало - не более 10 байт, и это ввод-вывод устройства, так что ... ну, это довольно сложно. Я был в состоянии задумать разумное обходное решение, хотя, в котором, если запрос аннулирования был сделан во время чтения, результат будет просто проигнорирован ... – Will

+0

Да, если «отменить и отказаться» - это жизнеспособный подход, общий совет приведенные в этих случаях: http://blogs.msdn.com/b/pfxteam/archive/2012/10/05/how-do-i-cancel-non-cancelable-async-operations.aspx –

Смежные вопросы