HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Async Yield and continue on TaskPool

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
continueasyncyieldtaskpooland

Problem

Using await task.ConfigureAwait(false) is a standard best practice for indicating to the compiler that the continuation does not need to be run on the current context.

We also have the Task.Yield() method which hands control back to the calling context and always posts a continuation (no fast-path optimizations); however, since this does not return a Task, you cannot use ConfigureAwait(false) and the continuation is always scheduled on the current synchronization context (if there is one).

Without running a task manually, I could not see a standard way of both yielding and ensuring/indicating that the continuation did not require the synchronization context.

I trimmed down the Task.Yield source code to create the TaskEx.YieldToThreadPool method below which returns an awaitable that always schedules its continuation on the TaskPool.

It could be used in any situation where a Yield makes sense and further Tasks use ConfigureAwait(false).

In addition, within non performance critical code, it could be used to ensure that the method is running on the TaskPool without manually spawning a Task, or splitting the method.

There could also be an additional check in the IsCompleted property to see if the current thread is already on the TaskPool and not yield.

I have tested the method and it functions as expected - however I would greatly appreciate the thoughts of the Async-Await gurus. Did I miss a fundamental concept that makes this wrong/unnecessary?

```
//Example usage:
public async Task MixedAsyncAndCpuBoundMethod()
{
await TaskEx.YieldToThreadPool();

//Now on ThreadPool thread, no risk of async-await 'fast-path' skipping-
//over the continuation.

CpuBoundWork();
Thread.Sleep(1000);

await AsyncMethod().ConfigureAwait(false);
}

///
/// Yields and schedules the continuation on the .
///
/// .
public static ToThreadPoolAwaitable YieldToThreadPool()
{
return new ToThreadPoolAwaitable();
}

public stru

Solution

First: this is a pretty tidy implementation and there is not much to say from the code review perspective.

Now about the question of necessity: Microsoft did include SwitchTo extension methods in the async CTP but decided to remove them because they were open to misuse. This doesn't mean something like this isn't useful but Microsoft has to consider a much wider audience and an innocuous SwitchTo call in the wrong place could easily lead to weird behaviors and random, hard to track down bugs causing potentially a fair amount of support work so they decided to not ship it (and also because it's reasonable easy to create yourself if you need it).

So essentially if you are careful to avoid using it within your own projects in potentially harmful places (like inside catch and finally blocks) this might be a nice tool in your library to have.

Context

StackExchange Code Review Q#110066, answer score: 4

Revisions (0)

No revisions yet.