First, using APM without a thread pool
APM allows the thread pool to invoke the specified callback method when the asynchronous operation completes. It uses very little resources and provides excellent performance, however, APM also allows three different ways to discover when an asynchronous operation is completed.
First, if a thread calls the EndXxx method before the operation completes and passes the IAsyncResult object, the calling thread blocks and waits for the operation to complete. EndXxx The returned result will wake the thread. Second, you can query the AsyncWaitHandle property of the IAsyncResult, thus get a WaitHandle, and then in this WaitHandle to increase the WaitOne, which is a thread blocking wait operation completed. However, both of these actions should be avoided because they block threads and may cause the thread pool to classify another thread.
The third to first thread can then query the IsCompleted property of the IAsyncResult continuously in a loop, thus discovering when the operation is complete. Polling, however, wastes CPU time.
Two, cannot cancel asynchronous I/O throttling operation
There is currently no way to cancel an in-progress asynchronous I/O throttling operation. Of course, for us to want such a function, but it is very difficult to achieve, and we have not yet seen the relevant examples. After all, if you request 1000 bytes from the server and then decide that you no longer need the data, there is no way to tell the server to forget your request. In this case, only bytes are returned as usual, and then discarded. In addition, there is a race condition where your cancellation instruction may be reading the last byte to arrive.
Third, memory consumption
Any time the Begin async method is called, it constructs an instance of the IAsyncResult interface. This means that an object will be created for each asynchronous operation that you want to perform. This adds some overhead and creates more objects in the heap, causing more garbage collection to occur. The end result is that the performance of the application is getting worse. Therefore, if you know that your I/O operations are executing very quickly, it might be more reasonable to synchronize.
Iv. issues peculiar to FileStream
When you create a FileStream object, you can specify whether to communicate synchronously or asynchronously through the fileoptions.asynchronous flag. This is equivalent to calling the Win32 CreateFile function and passing the FILE_FLAG_OVERLAPPED flag to him. If this flag is not specified. Windows synchronizes all file operations in a synchronized manner. Of course, you can still read asynchronously using the BeginRead method. For an application, the operation surface is asynchronous, but the FileStream class internally simulates the asynchronous behavior with another thread. This extra thread is purely wasteful and can affect performance.
In another aspect, you can create a FileStream object when you specify the fileoptions.asynchronous flag, and then you can call FileStream's Read method to perform a synchronous operation. Internally, the FileStream class starts an asynchronous operation and then immediately calls the thread to hibernate, knowing that the operation is complete before it wakes up to emulate the synchronization behavior. more efficient underground. But it's a little bit more efficient for the way it is.
Considerations for asynchronous Model (APM)