We currently have an interface for an asynchronous video decoder that runs on its own thread. Basically you feed it some data and it'll eventually call you back on its thread through some events, like so (not real code):
interface IDecoder {
void Decode(parameters);
event FrameReady;
event FrameDropped;
// lots of other possibilities
}
It's a bit messy and I'd like to convert it to a C#5, async-based version, something like:
interface IDecoder {
async Task<DecodeResult> DecodeAsync(parameters);
}
Where DecodeResult will have all the information that would have otherwise been transmitted via events, and the client code can be written cleanly with async/await rather than a mess of event handlers and thread dispatching.
It is my understanding that Tasks are scheduled on the ThreadPool by default. We want all Decode operations to happen sequentially on a single, decoder-specific thread. Can this be achieved using Tasks, if so, how? Are Tasks even appropriate for this use or is there a more obvious pattern I'm missing?
Best Answer
Task
s that are created usingTask.Run()
(orTask.Factory.StartNew()
, in the common case) are. But this does not apply toTask
s that don't execute any code themselves, like the ones that automatically created fromasync
methods, or the ones that are created usingTaskCompletionSource
.So, what you want is certainly possible. How exactly to do it depends on what should
DecodeAsync()
do.EDIT: Probably the simplest way to convert your current code to
Task
s would be usingTaskCompletionSource
. Simply callTaskCompletionSource.SetResult()
instead of invoking an event.But another option might be something like this:
This won't guarantee that all decoding is done on the same thread, but it does guarantee that the jobs will be executed one after the other.
Also, this code is not thread-safe: it won't work correctly if call
DecodeAsync()
at the same time from multiple threads. If you need that, use a lock.