I have read a lot on threading but can't figure out a way to make this one work right. So it should really be obvious how to do this as it usually is with me (always missing the obvious) :p
Here's my problem (BTW, am working with WPF in C#):
I have a long running process i'm running on a separate thread while the UI stays responsinve and showing evolution. However, mid-process, i need to ask the user to confirm a value before proceeding. That's what i can't figure out, cause the window to confirm the value must be run in the UI thread and still return the value to the work thread so it can continue it's work.
So...
Long running process beeing run in work thread
Work thread waits for UI Thread
UI thread shows the confirmation window
User confirms/fixes value and closes the confirmation window
UI thread sends result from confirmation window to work thread
work thread gets values from UI Thread (value was changed by user? to what?)
work thread continues long running process
Work thread gets values from confirmation window
I've already the work thread working well using ThreadPool - although am open to using threading in different ways (NET 4.5). Problem i am having is that if i send the confirmation window part to dispatcher my work thread won't wait for the results from the confirmation window. If i don't put in the dispatcher i get an exception about not beeing in an STA thread when the window constructor is called.
Any ideas welcome
You probably don't want to block the worker thread waiting on UI (not saying you couldn't do it, but it would be messy).
A much simpler solution would be to split up your process into two threads; one that runs pre-user input, and one that runs after. You would prompt the user upon the first thread's completion (via a callback or event).
Something like (pseudo-code)
InitialThreadObject.Completed += () =>
{
PromptForUI();
SecondThreadObject.Start();
}
InitialThreadObject.Start();
Obviously you would choose the completion notification mechanism based on your current code.
Related
I have Main() function which displays in label the current time. There is a button which calls a function LoadUserImage() for reading image files and writing them to database and then showing the result of reading and writing in another label. While LoadUserImage() is running I want the Main() function to still display in label the current time. My instructor tells me to put LoadUserImage() in a separate thread and then join it. But on his lectures he tells that Thread.Join() makes the main thread kind of pause temporarily The question is: if joining makes the main thread pause then how can it update the GUI in my case?
The purpose of Thread.Join() is to make sure that the background thread started previously is stopped properly, but it is not needed for the background thread to work.
In your case, you start the long-running operation in a background thread, and in the main thread proceed with the other activities. You need to call Thread.Join() only at the end, when the main thread has already finished its activity. If at that point the background thread had terminated already, Thread.Join() will return right away, while if the background thread is still busy, it will block (in the main thread) until the background thread has finished. This is the way to make sure an app is not exiting until operations are active in the background.
I suppose in your Main() (running in the main thread) you have some loop which periodically updates some UI. This loop has some exit condition (e.g. by reacting to pressing Enter in a Console.ReadLine(), or a Ctrl-C handler). Once the loop is exited, it can call Thread.Join().
If proper exit is not implemented at all in your sample program (which is not so nice, but usual in such sample program), then you don't have to call Thread.Join() at all! When the process exits, all threads disappear anyways.
Using System.Threading.Thread.Sleep( ) makes the entire application stop for the time taken in the arguments. I want other processes running while one process is waiting for a particular amount of time. To put it in short, I want another way other than System.Threading.Thread.Sleep( ) in my application that does not stop the entire thing.
Example: If I have a label that changes text every 5 seconds, I should be able to press a button which can do some other process, like changing an image.
Thread.Sleep() only puts the current thread to sleep. If it is the UI thread, this might block your application and it looks like it is completely blocked. Background threads are still running.
If you want to sleep without blocking, you could use the following code:
await Task.Delay(5000);
// continue here with your code, such as updating your label
This doesn't block the UI thread, just delays the proceeding of your function. You have to declare your method as async
I am not too informed about this so I am not sure this is the best way to do it
The Task.Wait Method
like that your main thread waits for the child thread to complete before continuing. From here on to your problem I guess just brains will help
an other helpful link:
Thread Synchronization
I have a large WPF app with few threads ( all threads use dispatcher.invoke to update the GUI) and many grids and controls. At any give time only 2 or three grids are visible so the user can interact with the controls. I also have an external device which sends a signal to my app and I then update the GUI so the user knows the signal was fired.
I do the update through a dispatcher since the signal detection is on another thread. So everything is fine until intermittently it takes 5 minutes for the dispatcher.invoke with normal priority to call my method. when this happens as soon as I click the GUI then method gets called immediately. So it seems that message pump is asleep or hung and as soon as I click on the GUI it wakes up and process my message. I have done this several times so I am sure that message queue wakes up upon refreshing the GUI.
So is this a bug in WPF message pump queue where it occasionally goes to sleep and wakes up when the GUI is refreshed? or what is the reason for this behavior and what to do about it.
Thanks in advance
I have a code that executes for some time on GUI thread (to simplify things, let's assume in Button_Click event).
When the method starts I'd like to show a message "Please wait", and continue working. When the work is done I'll hide the message and continue.
I know I can do this with BackgroundWorker (or any other Thread related), but I was hoping there's something already finished like:
MBox.Show("Please wait...");
//do my work...
MBox.Hide();
If you have some long running process, you should not be doing this in the UI thread. What is wrong with BackgoundWorker? That class is great! I would recommend that you use that if this is a WinForms app.
If you using .Net 4 you can run a Task to work with your background worker, else you can do threading, but they shouldn't be in same thread.
You could create your own form to do this. There is nothing inherently evil about making the user wait if they would expect to wait or are required to wait. We have applications where the normal work flow requires a short wait. Placing it in a background thread doesn't help the user since they still need to wait for the operation to finish before they can do anything else.
How do I keep my C# form that, lets say is in a for-loop, from locking up? Do I call Application.DoEvents(); before the loop or after? From what I've heard using the DoEvents method will keep my app from locking.
You should not use Application.DoEvents() in order to keep your application responsive.
Calling this method will allow any waiting windows messages to be dispatched. This means if a user clicks on a button (or performs any other user interaction) that action will be processed. This can therefore cause reentrancy. If they press the same button as the one that caused the loop you are processing you will end up having the routine called again before you have finished!
Instead you should use a BackgroundWorker thread to perform the long process and then once the action is completed perform whatever additional actions are required. For example, once a button is pressed you would start the worker thread and then disable you button so it cannot be pressed again. Once the worker thread completes you would enable the button again.
There are a few ways, this (DoEvents) just forces the message pump to process messages. Some people put a Thread.Sleep at the end of a loop (always inside the loop though) in a thread. What exactly are you doing in your thread, because there might be a better way to accomplish your goal overall?
If the process is causing the UI to lock up for an unacceptable amount of time, try using a seperate thread (either create it, use the thread pool, or use the BackgroundWorker class.