2014-12-08 2 views
13

Старый способ использования асинхронного ввода-вывода для FileStream состоит в использовании FileStream.BeginRead() и FileStream.EndRead().При использовании FileStream.ReadAsync() следует открыть файл в режиме async?

В документации MSDN для FileStream.BeginRead() состояний:

FileStream обеспечивает два различных режима работы: синхронный ввода/вывода и асинхронный ввод/вывод. В то время как любой из них может быть использован, базовые ресурсы операционной системы могут позволить доступ только в одном из этих режимов.

По умолчанию FileStream синхронно открывает дескриптор операционной системы. В Windows это замедляет асинхронные методы. Если используются асинхронные методы, используйте конструктор FileStream (String, FileMode, FileAccess, FileShare, Int32, Boolean).

.Net 4.5x способ выполнения асинхронного ввода/вывода для FileStream является использование Stream.ReadAsync().

Документация MSDN для FileStream.ReadAsync() ссылки непосредственно на документацию на номер Stream.ReadAsync(). В этой документации нет необходимости открывать файл в режиме async; действительно, пример кода в документации явно не делает этого.

Я поэтому предполагаю, что при использовании File.ReadAsync() нет необходимости открывать файл в асинхронном режиме.

Правильно ли это предположение?

[EDIT]

Я только что обнаружил an MSDN article on using Async for File Access.

Это говорит:

Примеры в этом разделе, используется класс FileStream, который имеет опцию, которая вызывает асинхронный ввод/вывод происходит на уровне операционной системы. Используя эту опцию, во многих случаях можно избежать блокировки потока ThreadPool.

Чтобы включить этот параметр, вы указываете useAsync = true или options = FileOptions.Asynchronous аргумент в вызове конструктора.

Так что теперь я думаю, что я должен открывать файл в асинхронном режиме ... Если это так, то немного жаль, что пример, приведенный в документации ReadAsync()делает не открыть файл асинхронно!

ответ

15

В win32 вам необходимо указать FILE_FLAG_OVERLAPPED, чтобы использовать асинхронный File IO. В мире .net вы используете isAsync параметр FileStream, чтобы достичь того же. Если вы этого не сделаете, операции не будут асинхронными.

Жаль, что FileStream.ReadAsync и связанные с ним методы не смогли его документировать.

Вы можете подтвердить это, взглянув на реализацию.

public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) 
{ 
    ... 
    if (!this._isAsync || !Environment.IsWindowsVistaOrAbove) 
    { 
     return base.ReadAsync(buffer, offset, count, cancellationToken); 
    } 
    ... 
    return stateObject; 
} 

base.ReadAsync в конечном счете звонить в Stream.Read метод синхронно в ThreadPool создается впечатление, что операция является асинхронной, но на самом деле нет.

Информация, связанная с Concurrent Programming On Windows книги (Pg: 818):

Как CreateFile, вы должны указать во время создания, которые вы бы хотели использовать FileStream для асинхронного выполнения. С FileStream вы делаете это, передавая true как аргумент isAsync для перегрузки конструктора, которые его принимают. Свойство stream IsAsync впоследствии вернет true. Если вы не смогли передать это значение , вызовы будут BeginRead и BeginWrite. Но они будут использовать реализацию базового класса из Stream, которая обеспечивает ни одно из преимуществ истинного асинхронного ввода-вывода файлов.

Выше информация о методах APM (так как это старая книга), но по-прежнему актуальна.

+1

Это очень важно знать! Кажется, что есть много веб-страниц, на которых обсуждается «ReadAsync()», но не упоминается этот очень важный факт (например, http://www.dotnetperls.com/async) –

+0

Да, связанный с вами сайт довольно хорош но, к сожалению, об этом не говорили. Я вижу, что эта ссылка говорит, что с помощью async мы используем только один поток и показываем пример с устройством чтения потоков. Это неправильно, потому что реализация использует «ThreadPool» без флага 'isAsync' :( –