I have a deadlock when I invoke the UI thread from a worker thread. Indeed, the worker thread is blocked on the invoke line:
return (ucAvancementTrtFamille)mInterfaceTraitement.Invoke(d, new object[] { psFamille });
The weird thing is that the UI Thread (which, correct me if I'm wrong, is the main thread) is idle.
Is there any way to:
see which thread I'm actually trying to invoke?
see what said thread is really doing?
We can see in the image below, the worker thread (ID 3732) blocked on the Invoke line, and the MainThread is idle in the main function of the application.
Edit: Here is the stack of the main thread:
Edit2: Actually, I paused the the program a second time, and here is what the stack looks like:
Edit3: Workaround found
I finally found a workaround. The problem is apparently due to an async wrapper race
condition issue. The workaround is to use BeginInvoke and wait for it with a timeout. When it times out, invoke it again and loop until it finally returns. Most of the time, it actually works on the second call.
IAsyncResult ar = mInterfaceTraitement.BeginInvoke(d, new object[] { psFamille });
while (!ar.AsyncWaitHandle.WaitOne(3000, false))
{
ar = mInterfaceTraitement.BeginInvoke(d, new object[] { psFamille });
}
// Async call has returned - get response
ucAvancementTrtFamille mucAvancementTrtFamille = (ucAvancementTrtFamille)mInterfaceTraitement.EndInvoke(ar);
It's not pretty but it's the only solution I found.
The Main thread doesn't look idle. Your screen shot shows it current location at ECM.Program.Main. That can't be correct, if it is idle then it is inside Application.Run(), pumping the message loop. Which is required for Invoke() to complete.
Double-click the main thread and switch to the Call Stack window to find out what it is really doing.
Have you tried using BeginInvoke instead of Invoke? BeginInvoke is asynchronous.
You are correct. The Main Thread is the entry point to the application which is normally the location of the call to Application.Run which gets the message loop going. So that should be the UI thread unless you have done something out of the ordinary in regards to the message loop which is unlikely.
In the Thread window you can right click on the Main Thread and select Switch to change the debugging context to that thread. The Call Stack window will then show the location of the current executing method.
If your worker thread really is blocked on the Control.Invoke call and the UI thread is idle as you claim then the problem could be with the execution of the instructions within the delegate that is being marshaled or the message loop as not yet been started. The later seems plausible since your screen shows the location of the Main Thread as Main.
Have you tried using a BackgroundWorker instead. If you use it it will save you a lot of this.Invoke and InvokeRequired calls.
I believe that if you create a new thread and make it execute the line you are showing you won't have a deadlock. I will try find old code of mine and post it here.
Are you using Visual Studio 2008 ?
If the answer is yes, you should try with Visual Studio 2010. It's a known bug.
Good luck !
Related
I am new to WPF and making it up as I go along so apologies if I have done anything drastically wrong.
I have a main window that makes a new 'error window' once particular user controls have completed their business. This new error window returns a 'loading placeholder' to UI whilst a background thread is updating another part of the 'error window'.
ErrorsWindow errorWindow = new ErrorsWindow();
errorWindow.LoadingPlaceholder.Text = string.Format(#"Loading...
Please wait {1} minutes and {0} seconds to see potential errors",
ConfigurationManager.AppSettings["ErrorWindowWaitSeconds"],
ConfigurationManager.AppSettings["ErrorWindowWaitMinutes"]);
errorWindow.Show();
this.Dispatcher.BeginInvoke((Action)(() =>
{
errorWindow.SetupWindow();
}), System.Windows.Threading.DispatcherPriority.Background);
So my errorWindow shows up in the UI with the loading placeholder text set correctly. The UI then waits 1 minute 30 seconds for the errorWindow.SetupWindow() method to complete. The issue is that during this wait period I cannot close the window until the errorWindow.SetupWindow() method has completed.
Is there a way to allow the window to close and just abort the background thread?
EDIT: I cannot use a backgroundworker or a task as I need to update the UI elements inside the errorWindow.SetupWindow() method
Thankyou in anticipation
Invoking anything on Dispatcher (if Dispatcher is of UI thread) will run your delegate on UI thread only. Hence, you can't close the window till UI thread is busy somewhere else.
Setting priority DispatcherPriority.Background won't make it run on background thread. It set's the delegate DispatcherPriority to Background. It means that all queued delegates on Dispatcher with priority higher than Background will run first before your delegate gets time to execute.
In case you want to run your operation on background thread, use Task or BackgroundWorker.
As per definition from MSDN:
Executes the specified delegate asynchronously at the specified
priority on the thread the Dispatcher is associated with.
As stated above it runs delegate on associated thread of dispatcher. (which might be in your case is UI thread).
I found the answer to my question on another stackoverflow post here:
How to make some Tasks change my WPF controls
It involves doing the long running task on another thread(using System.Task) then using the dispatcher on the separate thread to affect the UI thread with any UI related changes.
I am working on understanding how to use BeginInvoke correctly. I wrote up a small test in a console app where all I am trying to do is use BeginInvoke to call a function to make a 100x100 Window with a title pop up. I am failing miserably. Here is what I have, I know this is probably just poor understanding of Threads (not my strong suit), but I'm stuck, no window pops up I just end up at my readline in Main waiting for a keypress. Execution starts at ThreadUITest.
static void ThreadUITest()
{
ThreadStart starter = new ThreadStart(threadFunc1);
Thread test = new Thread(starter);
test.IsBackground = true;
test.SetApartmentState(ApartmentState.STA);
test.Start();
}
static void threadFunc1()
{
dispatcher = Dispatcher.CurrentDispatcher; //Statically declared earlier
ThreadStart starter = new ThreadStart(threadFunc2);
Thread test = new Thread(starter);
test.IsBackground = true;
test.Start();
}
static void threadFunc2()
{
Action method = Draw;
Console.WriteLine("I'm here!");
//dispatcher.BeginInvoke( (Action)(() => {Draw();}),DispatcherPriority.Render, null);
dispatcher.BeginInvoke(method, DispatcherPriority.Send, null);
}
static void Draw()
{
Window win = new Window();
win.Height = 100;
win.Width = 100;
win.Title = "A Window!";
win.Show();
}
Thanks for any help.
You need to add the following at the bottom of your threadFunc1
// statically declared earlier, although you don't need to keep a reference to it as
// WPF will keep it in Application.Current
application = new Application();
application.Run(); // thread1 is now our "UI" thread
Why does this solve it?
The Dispatcher object provides an interface for getting a thread to do some work for you (via BeginInvoke or Invoke).
In order for a thread to be able to process any "do work" messages, it must be running some kind of event loop, where it sits and waits for the next message to process - if it weren't doing this, then it wouldn't be able to process anything, it would just be stuck.
Calling Dispatcher.CurrentDispatcher from thread1 will create a new dispatcher on that thread if there isn't one already there[1] - that gives us our interface to post messages to the thread.
What dispatcher.BeginInvoke does is add an entry into the message queue for that thread, however the thread isn't running any message loop yet. We can queue messages to it, but it won't pick them up and run them - this is why nothing happens.
So, we need to make that thread start running a message loop.
The Application.Run() method is the WPF framework method which does exactly that. The Application.Run method never returns (until you call Application.Shutdown anyway), it starts up a message loop to begin processing messages thereafter. I find it useful to think of it "taking over" the thread.
Now with this change, when thread2func calls dispatcher.BeginInvoke, the message loop code inside Application.Run goes "oh look, a message, I'll process it" - it gets the BeginInvoke method, and does what it's told (in this case, executing your Draw function), and all is well
Note: As per Ark-kun's answer You can also just call Dispatcher.Run to start a message loop on that thread without creating an Application object (Application.Run does this internally). Generally I find it nicer to create an application object though, as that's more "normal", and some other code you may write later on may expect an Application object to exist
[1] FYI, this is why calling Dispatcher.CurrentDispatcher is dangerous and you should avoid it. If you call Dispatcher.CurrentDispatcher from the existing UI thread, it returns you a reference to the correct dispatcher.
If you accidentally call it from another thread, logically, you'd think it would return a reference to the existing dispatcher. But no - instead, it creates a second dispatcher, pointing at our other thread - however our other thread won't be running a message loop, and we'll get stuck again. I'd suggest never calling Dispatcher.CurrentDispatcher except for the very first time.
Once your app is up and running, you generally don't need to do this anyway, as all WPF objects (Window, Button, etc) all have a Dispatcher property which you can use to get the correct dispatcher from anyway
Try calling Dispatcher.Run() in the end of threadFunc1.
I'm using threading in my windows form application.
Code
Thread sqlProcessThread = new Thread(new ThreadStart(doSqlWork));
sqlProcessThread.IsBackground = true;
sqlProcessThread.Start();
When ever this thread is called from my form at that time the form got hang.
How can i solve this problem with out using background worker.
You can use property InvokeRequired to check UI acess from different thread.
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(this.updateUI));
return;
}
More information: MSDN documentation
If you use Invoke() from a background thread, it will wait for the UI to respond before continuing.
It's possible for the UI to respond to the Invoke() call by waiting on something which requires the background thread to do further processing. If that happens, you get deadlock.
If you do not require a return value from the UI call, you can often fix this by using BeginInvoke() instead of Invoke().
Calling BeginInvoke() will return immediately to the background thread that calls it, preventing the deadlock.
This has to be used with care.
I'm building an app using TPL in VS2010 Ultimate. The most of the times I run the app it becomes unresponsive when I Call DoRepresentation() from the UI's thread.
void DoRepresentation()
{
Parallel.ForEach(cgs, loopOptions, g =>
{
UpdateRepresentation(g);
});
}
void UpdateRepresentation(object g)
{
view.Invoke(new Action(() =>
{
representation = new MyRepresentation(g);
}));
}
I don't know why the app is becoming unresponsive. Am I having a deadlock?
Inside MyRepresentation I do some calls to OpenGL.
view is a Control inside Form1 (the main form).
When the app become unresponsive I pause it from the VS IDE and here's the info I get
In the "Parallel Tasks" window I get the following:
ID Status Message<br>
1 ?Waiting Task1 is waiting on object: "Task2"<br>
2 ?Waiting No waiting information available<br>
In the "Call Stack" window I get the following:
[In a Sleep, wait, or join]<br>
[External Code]<br>
Test.dll!Render.DoRepresentation()<br>
App1.exe!Form1.Button1_Click<br>
Any help will be appreciated.
Yes, you are having a deadlock. What Parallel.ForEach() does is that it runs the iterations using one or more threads including the current one and then blocks the current thread until all iterations are complete.
This means that if you call DoRepresentation() from the UI thread, you get a deadlock: the UI thread is waiting for iterations on other threads to finish, while those other threads are waiting for Invoke() to finish, which can't happen if the UI thread is blocked.
Also, in your case, using Parallel.ForEach() doesn't make any sense (assuming this is your actual code): you run new MyRepresentation() on the UI thread.
I don't understand what exactly is the code doing (it seems it overwrites representation in each iteration), but I think you should run ForEach() from a background thread. This means DoRepresentation() will return before it finishes its work and so Invoke() will work correctly.
In general, it's not a good idea to block the UI thread for a long time, so you should run any time-consuming code on another thread.
you can use the BeginInvoke insteed of Invoke Method. if you still need then you can lock an object and make sure that this will not be accessible from the other thread until its realized.
using the Begin Invoke Method
void UpdateRepresentation(object g)
{
view.BeginInvoke( new Action(() =>
{
representation = new MyRepresentation(g);
}));
}
Using the Lock
void UpdateRepresentation(object g)
{
lock(this)
{
view.Invoke(new Action(() =>
{
representation = new MyRepresentation(g);
}));
}
}
This comment applies to my specific app, which is a Windows app in C#: Using a Lock did not work for me either, and the application just froze up.
BeginInvoke worked, but I didn't like the effect of having UI controls being updated asynchronously.
I ended up starting the main process as a separate thread (System.Threading.Tasks.Task), which would start and instantly give me back control of the main thread. Afterwards, while waiting for several other tasks to end execution in a loop, I also ended up having to insert this line: System.Windows.Forms.Application.DoEvents() to enable the system to process all messages waiting in the queue. Now it works right for my application. There might be another way to skin this cat, but it works now.
I'm showing an animation while my control is loading the data. When the thread finishes, I hide the animation and show the control. So I'm executing this code from a thread:
protected void InvokeEnableBackControl()
{
if (this.InvokeRequired)
{
this.Invoke(new OpHandler(EnableBackControl));
}
else
{
EnableBackControl();
}
}
Sometimes, when I execute this code, the main thread gets hanged in the following code:
protected virtual void EnableBackControl()
{
if (overlayAnimation.TargetControl != null)
{
overlayAnimation.TargetControl.BringToFront();
}
overlayAnimation.SendToBack();
overlayAnimation.Enabled = false;
overlayAnimation.Visible = false;
}
I'm not sure if it's hanged setting the Enable or Visible property. Do you know any circumstance that may hand the application calling these properties from a Control.Invoke?
Note that Control.Invoke is synchronous, so it will wait for EnableBackControl() to return. Consider using Control.BeginInvoke, which you can "fire and forget."
See this answer: What's the difference between Invoke() and BeginInvoke()
I've run into problems before when I'm executing .Invoke on a background thread while my main thread is still busy - this gives the impression that the app is hung, because the .Invoke just sits there, waiting for the main thread to respond that it's paying attention. Possible causes:
Your main thread is blocked waiting for something
Your main form currently had a modal dialog up, so it's not listening to new requests
Your main thread is spinning, either continually checking if something is finished or doing new work. In my case, the main thread spent the first minute spinning up background threads in a tight loop, so it wasn't listening for any .Invoke requests from background threads.
When you attach the debugger, pay special attention to what your main control MessagePump thread is doing - I suspect its lack of attention is the cause of your trouble. If you identify that it's a tight loop in your main thread that's not responding, try inserting a .DoEvents in the loop, which will pause execution and force the main thread to empty the message pump and route any outstanding requests.
Run in debug, make app hang and then pause debug in Visual Studio and inspect threads.
What I discovered is that the actual drawing/painting of controls can be quite slow, esp if you have a lot of them and/or use double buffering for smooth refresh. I was using BeginInvoke to update a listview control from data I was receiving from a socket. At times the updates were happening so fast that it was freezing the app up. I solved this by writing everything I received in the sockets async receive to a queue, and then in a seperate thread dequeuing the data and using BeginUpdate and EndUpdate on the listview and doing all the outstanding updates in between. This cut out a ton of the extra redrawing and made the app a lot more responsive.
You have to use BeginInvoke inested Invoke see this Link