1

What is a good way with the TPL to create a task that doesn't do anything itself, but exists solely to be awaited on until some other event in the system triggers it with data for the task to return?

If the triggering event is itself a Task or follows the IAsyncResult pattern that FromAsync expects, then support is built in. But what the event is of a different form?

Unsatisfying solution:

The closest I could come is to create the task that when executed returns a value contained by a mutable object. Here's an example using a 1-element array as the mutable object:

var task = new Task<ReturnType>(
    resultContainer => ((ReturnType[])resultContainer)[0],
    new ReturnType[1]);

Somewhere else in the code, when the event occurs, the result container's content is set and the task is started:

((ReturnType[])task.AsyncState)[0] = theResult;
task.Start();

This allows some other code to await the task:

ResultType result = await task;

Left-nostril code smell: Having to start a task and execute its entry point method when there isn't any real work done in the task.

Right-nostril code smell: The holder object whose only purpose is to contain the task return value.

Anyone care to clear the air?

Edward Brey
  • 40,302
  • 20
  • 199
  • 253

1 Answers1

0

Use TaskCompletionSource<T>. Create the source like this:

var source = new TaskCompletionSource<ReturnType>();
Task task = source.Task; // Hand this off to the awaiting code.

When the event occurs, set the result like this:

source.SetResult(theResult);
Edward Brey
  • 40,302
  • 20
  • 199
  • 253
  • If you don't need the result (just an indication of when done and success/failure), use `TaskCompletionSource` with a dummy type ([more info](http://stackoverflow.com/a/11969255/145173)). – Edward Brey Jun 23 '13 at 04:54