Deadlock when calling Dispatcher.Invoke () twice
I have two dispatchers:
dispatcher1
dispatcher2
Now when I call (this is a simplified sample of my complex code):
var ret = dispatcher1.Invoke(() => {
return dispatcher2.Invoke(() => {
return new object();
});
});
I'll run into a dead end.
call
dispatcher1.Invoke()
now waiting in
DispatcherSynchronizationContext.Wait()
and also dispatcher2 after the call
dispatcher2.Invoke()
waiting in
DispatcherSynchronizationContext.Wait
I am unable to change the callbacks for asynchronous calls (BeginInvoke) because I need the result.
This has not been the case since .NET 4.0 - only since I changed to .NET 4.5.
Is there a way to solve this problem?
source to share
This is a really scary solution, and you shouldn't use it. Ever.
But if you feel like your life is dangerous, try replacing your calls Invoke
with the extension method InvokeAndPump
below. (Don't replace every call with Invoke
in your project - just problematic in the question.)
public static class DispatcherExtensions
{
public static T InvokeAndPump<T>(
this Dispatcher dispatcher,
Func<T> function,
DispatcherPriority priority = DispatcherPriority.Normal)
{
if (dispatcher == null)
throw new ArgumentNullException("dispatcher");
if (function == null)
throw new ArgumentNullException("function");
// If you've found this code in your project, you are doomed. <3
Action wait, notify;
var currentDispatcher = Dispatcher.FromThread(Thread.CurrentThread);
if (currentDispatcher != null)
{
var frame = new DispatcherFrame();
wait = () => Dispatcher.PushFrame(frame);
notify = () => frame.Continue = false;
}
else
{
var waitEvent = new ManualResetEventSlim(false);
wait = waitEvent.Wait;
notify = waitEvent.Set;
}
var error = default(Exception);
var result = default(T);
dispatcher.BeginInvoke(
priority,
new Action(
() =>
{
try { result = function(); }
catch (Exception e) { error = e; }
finally { notify(); }
}));
// Hold on to your butts...
wait();
if (error != null)
throw new TargetInvocationException(error);
return result;
}
}
Seriously, though: heaven is helping anyone who uses it and hopes it will work reliably. I'm only posting this out of curiosity and because I'm angry. Mostly evil.
source to share