Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
456 views
in Technique[技术] by (71.8m points)

c# - When using FileStream.ReadAsync() should I open the file in async mode?

The old .Net way of performing asynchronous I/O for a FileStream is to use FileStream.BeginRead() and FileStream.EndRead().

The MSDN documentation for FileStream.BeginRead() states:

FileStream provides two different modes of operation: synchronous I/O and asynchronous I/O. While either can be used, the underlying operating system resources might allow access in only one of these modes.

By default, FileStream opens the operating system handle synchronously. In Windows, this slows down asynchronous methods. If asynchronous methods are used, use the FileStream(String, FileMode, FileAccess, FileShare, Int32, Boolean) constructor.

The .Net 4.5x way of performing asynchronous I/O for a FileStream is to use Stream.ReadAsync().

The MSDN documentation for FileStream.ReadAsync() links directly to the documentation for Stream.ReadAsync(). This documentation does not mention any need to open the file in async mode; indeed, the sample code in the documentation manifestly does not do so.

I therefore assume that when using File.ReadAsync() there is no need to open the file in async mode.

Is this assumption correct?

[EDIT]

I have just discovered an MSDN article on using Async for File Access.

This states:

The examples in this topic use the FileStream class, which has an option that causes asynchronous I/O to occur at the operating system level. By using this option, you can avoid blocking a ThreadPool thread in many cases.

To enable this option, you specify the useAsync=true or options=FileOptions.Asynchronous argument in the constructor call.

So now I'm thinking that I should be opening the file in asynchronous mode... If so, it's somewhat unfortunate that the sample code provided in the documentation for ReadAsync() does not open the file asynchronously!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In win32, you need to specify FILE_FLAG_OVERLAPPED to make use of asynchronous File IO. In .net world you use isAsync parameter of FileStream to achieve the same. If you fail to do so, operations will not be asynchronous.

It is a shame that FileStream.ReadAsync and its related methods failed to document it.

You can confirm this by peeking into the implementation.

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 will eventually call to Stream.Read method synchronously in ThreadPool giving the impression that operation is async, but really not.

Related information from Concurrent Programming On Windows book (Pg:818):

As with CreateFile, you must specify at creation time that you'd like to use a FileStream for asynchronous execution. With FileStream, you do this by passing true as the isAsync argument to the constructor overloads, which accept it. The stream's IsAsync property will subsequently return true. If you fail to pass this value, calls to BeginRead and BeginWrite will succeed. But they will use the base class implementation from Stream, which provides none of the benefits of true asynchronous file I/O.

Above information is about APM methods(as this is old book) but still relevant one.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...