Chapter 7. Interop

Asynchronous, parallel, reactive—each has its place, but how well do they work together?

In this chapter, we’ll look at various interop scenarios where we will learn how to combine these different approaches. We’ll learn that they complement each other, rather than compete; there is very little friction at the boundaries where one approach meets another.

7.1. Async Wrappers for “Async” Methods with “Completed” Events

Problem

There is an older asynchronous pattern that uses methods named OperationAsync along with events named OperationCompleted. You wish to perform an operation like this and await the result.

Tip

The OperationAsync and OperationCompleted pattern is called the Event-based Asynchronous Pattern (EAP). We’re going to wrap those into a Task-returning method that follows the Task-based Asynchronous Pattern (TAP).

Solution

You can create wrappers for asynchronous operations by using the TaskCompletionSource<TResult> type. This type controls a Task<TResult> and allows you to complete the task at the appropriate time.

The following example defines an extension method for WebClient that downloads a string. The WebClient type defines DownloadStringAsync and DownloadStringCompleted. Using those, we can define a DownloadStringTaskAsync method as such:

public static Task<string> DownloadStringTaskAsync(this WebClient client,
    Uri address)
{
    var tcs = new TaskCompletionSource<string>();

    // The event handler will complete the task and unregister itself.
    DownloadStringCompletedEventHandler ...

Get Concurrency in C# Cookbook 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.