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.
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.
My thread:
public void main_news_thread(MainApplication main)
{
ThreadPool.QueueUserWorkItem(p => check_news(validrsslist, 0));
}
I call this thread every interval of time...
How can I know when the thread finishes so I can call two other methods which deal with the GUI? How can I refer to this threadpool thread?
Since you are talking about UI, you might want to look at BackgroundWorker, which offers a RunWorkerCompleted event that fires on the UI thread, and indicate success/failure/cancel etc.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker_events.aspx
Personally, though, I'd just run a callback method at the end of my worker code (remembering to switch back to the UI thread, via Dispatcher.Invoke in WPF or this.Invoke in winforms).
You can execute the methods in the thread itself (you have to take care of invoking yourself to access the gui thread):
ThreadPool.QueueUserWorkItem(p => {
check_news(validrsslist, 0);
//do something after the task is finished
});
It is not entirely clear to me how many Dispatchers there are in an application and how they are related to, or referenced from Threads.
As I understand it, a WPF application has 2 threads (one for input, the other for UI) and 1 dispatcher (associated to the UI-Thread). What if I create another thread - let's call it "worker thread" - when I call Dispatcher.CurrentDispatcher on the worker thread, which dispatcher will i get?
Another case:
Assume a console application with 2 threads - the main thread, and an input-thread. On the main thread, I first create the input-thread and then i call Application.Run()
Thread thread = new Thread(new ThreadStart(UserInputThreadFunction));
thread.Start();
Application.Run();
There will be one dispatcher, right? On the input-thread, does Dispatcher.CurrentDispatcher return the dispatcher of the main thread? Or what is the proper way of getting an instance to the main thread's dispatcher?
Could it be, that there are more than one dispatcher in a WPF application? Is there any case, it would make sense to create another dispatcher?
WPF application has 2 threads (one
for input, the other for UI)
This statement is not entirely correct. A WPF application has only one UI thread that handles all the UI interaction and user input. There is also a "hidden" thread responsible for rendering, but normally developers don't deal with it.
Dispatcher / Thread relationship is one to one, i.e. one Dispatcher is always assoticated with one thread and can be used to dispatch execution to that thread. Dispatcher.CurrentDispatcher returns the dispatcher for the current thread, that is, when you call Dispatcher.CurrentDispatcher on a worker thread you get a dispatcher for that working thread.
Dispatchers are created on demand, which means if you access Dispatcher.CurrentDispatcher and there is no dispatcher associated with the current thread, one will be created.
That being said, the number of dispatchers in the application is always less or equal to the number of threads in the application.
WPF application by default has only one Dispatcher. The dispatcher is the only thread that will allow you to interact with UI elements. It abstracts implementations from you, so you only need to worry about being on the UI thread ie the Dispatcher.
If you are trying to directly interact with a visual (eg, set a text on a text box using txtBkx.Text = "new"), from a worker thread, then you will have to switch to a UI thread:
Application.Current.Dispatcher.Invoke(
() => { txtBkx.Text = "new"; });
Alternatively you can use SynchronizationContext.Current (while on a UI thread) and use that to execute delegates on a UI thread from a different thread. As you should note that Dispatcher.CurrentDispatcher may not always be set.
Now you can in fact create different WPF windows in the same application and have an individual dispatcher for each window:
Thread thread = new Thread(() =>
{
Window1 w = new Window1();
w.Show();
w.Closed += (sender2, e2) =>
w.Dispatcher.InvokeShutdown();
System.Windows.Threading.Dispatcher.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
As a side note remember in MVVM, you can update model from a non UI thread and raise property changed events from a non UI thread, as WPF will marshal PropertyChanged events for you. Raising CollectionChanged has to be on a UI thread though.
A dispatcher is always associated with a thread and a thread can have at most one dispatcher running at the same time. A thread does not need to have a dispatcher.
By default there is only one Dispatcher - For the UI. Sometimes it makes sense to have other dispatchers, other time it does not. A dispatching thread needs to block in the Dispatcher.Run() method in order to process invokes to the dispatcher. A thread such as your console input thread will not be availible to process invokes.
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 !
I am having a problem, for which I am not able to find a solution. The problem is as follows:
In the main thread (the default thread), I am starting a thread and then immediately in the main thread, I wait for the thread's exit by calling Thread.Join on the spawned thread. When I do that if the spawned thread tries to callback in the main thread's context by calling Dispatcher.Invoke, it hangs. Any ideas how I can allow the callback?
The callback has the logic to signal the thread to exit. Without executing the callback, the thread will never exit, and so the main thread is also stuck.
What's the point of starting a new thread if you just wait for it to complete ? Just do the work on the main thread...
I'm not exactly sure what you are asking but you may try BeginInvoke instead of Invoke
If you're only going to be waiting on the thread to terminate, you could simply have a polling loop, like this:
// var otherThread = ...;
volatile bool terminate = false;
while (!terminate)
{
Thread.Sleep(100);
}
otherThread.Join();
Then, leave it up to the callbacks to set the terminate flag to true once you're ready to join.
I had a similar problem which I finally solved in this way:
do{
// Force the dispatcher to run the queued operations
Dispatcher.CurrentDispatcher.Invoke(delegate { }, DispatcherPriority.ContextIdle);
}while(!otherthread.Join(1));
This produces a Join that doesn't block because of GUI-operations on the other thread.
The main trick here is the blocking Invoke with an empty delegate (no-operation), but with a priority setting that is less than all other items in the queue. That forces the dispatcher to work through the entire queue. (The default priority is DispatcherPriority.Normal = 9, so my DispatcherPriority.ContextIdle = 3 is well under.)
The Join() call uses a 1 ms time out, and re-empties the dispatcher queue as long as the join isn't successful.