rory.ap
rory.ap

Reputation: 35318

How to achieve "true" asynchrony

In his answer to this question, Stephen Cleary refers to "fake" asynchrony and "true" asynchrony.

there's a much easier way to schedule work to the thread pool: Task.Run.

True asynchrony isn't possible, because you have a blocking method that you must use. So, all you can do is a workaround - fake asynchrony, a.k.a. blocking a thread pool thread.

How then is it possible to achieve true asynchrony, like the various methods in System.Threading.Tasks.Task? Aren't all "truly asynchronous" methods just blocking operations on some other thread if you dig deep enough?

Upvotes: 4

Views: 1281

Answers (2)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149628

Aren't all "truly asynchronous" methods just blocking operations on some other thread if you dig deep enough?

On the contrary. Truely asynchronous methods are async all the way down to the OS level. These types of methods by default dont block even at the device driver level, using IRP (IO request packet) and DPC.

See How does running several tasks asynchronously on UI thread using async/await work? where i went into detail as of how overlapped IO works all the way down.

How then is it possible to achieve true asynchrony, like the various methods in System.Threading.Tasks.Task?

A Task represents a unit of work which will complete in the future. This has nothing to do with async IO. The reason you might assume that is because async-await works together nicely with awaitables. Most of the BCL libraries expose async IO operations via the TaskAwaiter, and that's why you assume it is the one achieving the asynchrony.

Upvotes: 6

i3arnon
i3arnon

Reputation: 116636

Aren't all "truly asynchronous" methods just blocking operations on some other thread if you dig deep enough?

No. Truly asynchronous operations don't need a thread throughout the entire operation and using one limits scalability and hurts performance.

While most truly asynchronous operations are I/O ones, that can get too overly complicated to understand. (For a deep dive read There Is No Thread by Stephen Cleary).

Let's say for example that you want to await a user's button click. Since there's a Button.Click event we can utilize TaskCompletionSource to asynchronously wait for the event to be raised:

var tcs = new TaskCompletionSource<bool>();
_button.Click += (sender, EventArgs e) => tcs.SetResult(false);
await tcs.Task;

There's no non-generic TaskCompletionSource so I use a bool one with a dummy value. This creates a Task which isn't connected to a thread, it's just a synchronization construct and will only complete when the user clicks that button (through SetResult). You can await that Task for ages without blocking any threads whatsoever.

Task.Delay for that matter is implemented very similarly with a System.Threading.Timer that completes the awaited task in its callback.

Upvotes: 8

Related Questions