- Overview of Asynchrony
- The Old-Fashioned Way: Event-Based Asynchrony
- The Old-Fashioned Way: The Asynchronous Programming Model
- The Modern Way: The Async Pattern
- Getting Started with Async/ Await
- Exception Handling in Async
- Implementing Task-Based Asynchrony
- Cancellation and Progress
- Asynchronous Lambda Expressions
- Asynchronous I/O File Operations in .NET 4.6
- Debugging Tasks
The Old-Fashioned Way: The Asynchronous Programming Model
The Asynchronous Programming Model (APM) is still based on threading. In this model, an operation is launched on a separated thread via a method whose name starts with Begin (e.g., BeginWrite). A method like this must accept, among its parameters, an argument of type IAsyncResult. This is a special type used to store the result and the state of an asynchronous operation. The most important members of this interface are two properties: AsyncState (of type Object), which represents the result of the operation under the form of either a primitive or a composite type, and IsCompleted (of type Boolean), which returns if the operation actually completed. As another parameter, these methods must receive a delegate that will be executed when the asynchronous operation is completed. Within this delegate, you will be able to analyze the result of the asynchronous operation, but you will also need to explicitly end the asynchronous operation by invoking a method whose name starts with End (e.g., EndWrite). Some classes in the .NET Framework are built to be APM-ready, such as Stream and its derived classes. So, to demonstrate how APM works, a good example can be based on the FileStream class. The following code demonstrates how to write some bytes to a stream asynchronously and how the callback receives information from the caller with IAsyncResult.
Private Sub OpenStreamAsync() Dim someBytes(1000) As Byte Dim randomGenerator As New Random() 'Generate a random sequence of bytes randomGenerator.NextBytes(someBytes) Using fs As New FileStream("Somedata.dat", FileMode.Create, FileAccess.Write) Dim result As IAsyncResult = fs.BeginWrite(someBytes, 0, someBytes.Length, AddressOf fs_EndWrite, fs) End Using End Sub Private Sub fs_EndWrite(result As IAsyncResult) Dim stream As FileStream = CType(result.AsyncState, FileStream) stream.EndWrite(result) 'Additional work goes here... End Sub
The IAsyncResult.AsyncState property contains the actual data sent from the caller and must be explicitly converted into the type that you need to work with; in this case, the stream. The reason is that you also must explicitly invoke the EndWrite method that finalizes the asynchronous operation. You can also pass custom objects as the IAsyncResult argument for the callback, to pass more complex and detailed information that you might need to elaborate when the task completes.