Async / await and opening FileStream?

I came across the following question, trying to determine if I used Stream methods like ReadAsync and CopyToAsync : C # 4.5 vs async file reading performance scenario

In this question, I read the following in the accepted answer:

In particular, your asynchronous test does not use asynchronous I / O; With the file streams,, you must explicitly open them as asynchronous, otherwise you just perform synchronous operations in the background thread.

In his asynchronous IO code, he used the following to open FileStream 'asynchronously':

 var file = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true) 

So, I was wondering if you are going to use methods such as CopyToAsync , should you open the underlying FileStream as shown above?, And not do something simple, like the following:

 File.Open(filename, FileMode.Open) 

Here's an example in the actual documentation for CopyToAsync to open the underlying FileStream : https://msdn.microsoft.com/en-us/library/hh159084(v=vs.110).aspx

If it doesn't matter how the underlying FileStream opens, what does the useAsync parameter of the useAsync constructor do?

+14
source share
3 answers

So, I was wondering if you intend to use methods like CopyToAsync, should you open the underlying FileStream as shown above?

Yes. The reason is mostly historical.

Firstly, on Windows HANDLE (including file descriptors) it must be open / created explicitly with an asynchronous flag if you want to make asynchronous ( OVERLAPPED ) on them .

However, the old Windows 95/98 / ME line only supports asynchronous serial port and IOCTL (device driver) operations . Asynchronous I / O on disk files was not supported on this platform. And the original .NET supported 98 / ME , so the original FileStream used only synchronous I / O. I think (but not quite sure) that the APM methods (for example, FileStream.BeginRead ) on Win98 / ME were probably just implemented using the so-called “called asynchronous delegates” (which simply execute a synchronous method like FileStream.Read in a thread pool thread).

So, the historical reason why file stream descriptors were not opened with the default asynchronous flag.

Here's an example in actual documentation for CopyToAsync

Unfortunately, many MSDN examples are of rather poor quality. They are fine if you approach them in terms of “here is an example of how to name this particular method,” but not so great in terms of “here is an example of production quality code that uses this method.”

+9
source

So, I was wondering if you intend to use methods like CopyToAsync, should you open the underlying FileStream as shown above, and not do something simple like File.Open ?

I used ILSpy to decompile and looked at File.Open .

 public static FileStream Open(string path, FileMode mode) { return File.Open(path, mode, (mode == FileMode.Append) ? FileAccess.Write : FileAccess.ReadWrite, FileShare.None); } 

What is called:

 public static FileStream Open(string path, FileMode mode, FileAccess access, FileShare share) { return new FileStream(path, mode, access, share); } 

And this particular FileStream constructor goes false for the useAsync parameter. So yes, that seems to matter. However, you can still use the async API, and it will still work the way you expected.

As Hans Passant says:

The base call to CreateFile() uses the FILE_FLAG_OVERLAPPED option. This allows overlapping I / O , a mechanism that allows asynchronous read and write at the winapi level.

The FileStream class has _isAsync bool, and that means: "If async IO is not supported on this platform or if this FileStream was not opened using FileOptions.Asynchronous.".

Again, you still get Task , which is an asynchronous operation of your choice.

+6
source

The MSDN website says:

useAsync

Type: System.Boolean

Indicates whether to use asynchronous I / O or synchronous I / O. However, note that the underlying operating system may not support asynchronous I / O, so if true specified, the handle can be opened synchronously depending on the platform. When opened asynchronously, BeginRead and BeginWrite work better on large reads or writes, but they can be much slower for small reads or writes. If your application is intended to use asynchronous I / O, set useAsync to true . Using asynchronous I / O can correctly speed up applications, the coefficient is 10, but using it without redesigning the application for asynchronous I / O can reduce performance by as much as 10.

+1
source

Source: https://habr.com/ru/post/1216656/


All Articles