This is an interesting problem, because (as you rightly point out) GifBitmapDecoder
inherits from DispatcherObject
. This means it has an implementation which does not allow just any thread to invoke its operations.
To work with any DispatcherObject
you should make calls through its Dispatcher
property. The returned Dispatcher
object lets you schedule delegates against the real object in a way that's compatible with its internal threading model via InvokeAsync
:
var decoder = new GifBitmapDecoder(...);
var operation = decoder.Dispatcher.InvokeAsync(() => { }); // Do things here!
This pattern, rather than returning a TPL Task
returns a DispatcherOperation
(presumably because it pre-dates TPL). This very task-like object lets you examine the state of the operation and get any results. It's also awaitable, meaning you can use it with await
just like a TPL Task
:
await decoder.Dispatcher.InvokeAsync(() => { });
In your specific problem, you should use this pattern in your OpenCompleted()
method. You will probably want to make it OnCompletedAsync()
and return a Task
to enable you to capture the UI Synchronization Context for your continuations and let the TPL handle marshalling calls back from the Dispatcher
to the UI thread.
public async void OpenFileAsync(string filename, bool forceReload = false)
{
FDecoder = await OpenFileTask(filename, forceReload);
await OpenCompletedAsync();
}