Last month I asked the following question which resulted in my learning of TaskEx.Yield
:
Can async methods have expensive code before the first 'await'?
However, I have since realized that this method actually submits all subsequent code to the ambient TaskScheduler
. In true DI spirit, our team has agreed to avoid using ambient instances where possible, so I would like to know if it's possible to explicitly specify a TaskScheduler
to use?
Something like the following would be great:
public static YieldAwaitable Yield(TaskScheduler taskScheduler)
{
return new YieldAwaitable(taskScheduler);
}
However, the current implementation of Async CTP only offers:
public static YieldAwaitable Yield()
{
return new YieldAwaitable(SynchronizationContext.Current ?? TaskScheduler.Current);
}
Would the following provide an acceptably efficient alternative?
await Task.Factory.StartNew(() => { }, CancellationToken.None, TaskCreationOptions.None, this.TaskScheduler);
In true DI spirit, our team has agreed to avoid using ambient instances where possible...
The async language support is based around an implicit scheduling context. I don't see the need for dependency injection here. Any method calling your async
method may supply its own context if necessary.
Your alternative:
await Task.Factory.StartNew(() => { }, CancellationToken.None, TaskCreationOptions.None, this.TaskScheduler);
will not work as expected. This will queue a noop lambda to a specific TaskScheduler
and then resume the method on the implicit scheduling context.
An earlier version of the Async CTP did provide a "yield to another context" method, called SwitchTo
. It was removed because it's too easy to misuse.
Personally, I think it's cleaner to keep your async
code using its implicit scheduling context, which is provided by its calling method.
P.S. It's not (too) difficult to create and install your own context, e.g., for testing purposes. I wrote AsyncContext
as a simple scheduling context for unit testing and Console programs. The Async CTP comes with GeneralThreadAffineContext
, WindowsFormsContext
, and WpfContext
for testing. Any of these can be installed using SynchronizationContext.SetSynchronizationContext
. IMO, DI is overkill.