Appendix B. Recognizing and Interpreting Asynchronous Patterns

The benefits of asynchronous code have been well understood for decades before .NET was invented. In the early days of .NET, several different styles of asynchronous code were developed, used here and there, and eventually discarded. These were not all bad ideas; many of them paved the way for the modern async/await approach. However, there’s a lot of legacy code out there that uses older asynchronous patterns. This appendix will discuss the more common patterns, explaining how they work and how to integrate them with modern code.

Sometimes, the same type is updated over the years, acquiring more and more members as it supports multiple asynchronous patterns. Perhaps the best example of this is the Socket class. Here are some of the members of the Socket class for the core Send operation:

class Socket
{
  // Synchronous
  public int Send(byte[] buffer, int offset, int size, SocketFlags flags);

  // APM
  public IAsyncResult BeginSend(byte[] buffer, int offset, int size,
      SocketFlags flags, AsyncCallback callback, object state);
  public int EndSend(IAsyncResult result);

  // Custom, very close to APM
  public IAsyncResult BeginSend(byte[] buffer, int offset, int size,
      SocketFlags flags, out SocketError error,
      AsyncCallback callback, object state);
  public int EndSend(IAsyncResult result, out SocketError error);

  // Custom
  public bool SendAsync(SocketAsyncEventArgs e);

  // TAP (as an extension method)
  public Task<int> SendAsync(ArraySegment ...

Get Concurrency in C# Cookbook, 2nd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.