Application.DoEvents(); - c#

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.

Related

is Thread.Join() a good way to let main thread update GUI while a thread func is working

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.

How do you make the application wait and keep other processes running at the same time in C#?

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

C# background worker

I have a task running in backgroundworker. on clicking the start button user starts the process and have got one cancel button to cancel the processing.
When user clicks on cancel, I would like to show a message box that "Process has not been completed , do you want to continue".
Here I want the processing which is left to be done only after user input. Till then want to halt the back ground thread. Can anyone help me on this. Is there anyway to halt the background worker for some time .Any kind of help will be appreciated.
Not built in. You could tell your code to (on every [n] loop iterations, etc) check something like a ManualResetEvent to see if it should keep running (at the same time it checks for cancellation). I don't recommend suspending the thread (Thread.Suspend), since you don't know what locks etc it may hold at the time.
On the other hand... why not let it run until you know it should be cancelled? Then you just need to check for cancellation (there is a flag for this) every [n] iterations...
If the BackgroundWorker is working on an object that is visible to both threads, you could 'lock' that object while waiting for the user to answer the question in a dialog box. This will cause the worker's thread to halt until the dialog-generating thread ends the lock.

How to show progress status for a long-time-consuming function?

I have a windows form simply like this: 1) a button when clicked will perform an operation taking a long time to complete, 2) a label showing how much percentage of the progress is going on.
In the long operation I mentioned, I write the code to update the Text property of the label but it doesn't work!
Please help me to show the progress status correctly.
You can take a look at the BackgroundWorker class (see the MSDN overview). It allows you to run some long-running operation in background and report progress updates (percentage) and completion from the background task to the user interface. Note that you'll need to calculate the progress percentage yourself.
However, the BackgroundWorker class takes care of other tricky aspects, such as sending your progress reports to the main GUI thread (where you can safely update the user interface).
Your going to want to create a worker thread that performs the task and occasionally reports its update to the form thread. If you do all of your work in the UI thread, your UI will be locked and won't update the progress/label correctly.
Before you start the worker thread, calculate the total number of steps you believe the process will take. Start the worker thread. After each unit of work, you Invoke an update method on the UI thread to increment the process.
You'll want to look at the BackgroundWorker class.
If your application will have several of these, I recommend creating a process interface (e.g. IProgressProcess). This interface will contain methods for executing a process and reporting updates. You will create all of your process classes by implementing from this interface. Write a control that contains a progress bar and accepts an IProgressProcess through a constructor or property. It can then use your custom process to execute and move along the progress bar. Then you can have your custom progress control send events when the process is complete or canceled.
This usually happens if you try to update the UI on the same thread where the operation is occurring. There are a couple of different ways that you could accomplish this.
You can update the UI with the BeginInvoke method.
You can use a BackgroundWorker component.
The reason that you don't see any change, is that the change causes a message to redraw the label, but the main thread is busy working so it doesn't respond to the message.
The simplest solution would be to just call the Application.DoEvents after updating the label. That works as a quick fix for your immediate problem, but it still will leave the application unresponsive in any other way.
The good solution would to start the operation in a separate thread. That way your main thread is free to handle messages while the operation is running. However working in a separate thread means a litte more work when communicating with the UI. If you want to update controls, you have to use the Invoke method to start a method that runs in the main thread so that it has access to the controls. Alternatively you can just update a variable in the thread, and have a timer control that periodically checks for changes in the variable and updates the label accordingly.

C# Winforms How to update toolStrip in function

I'm building a UI for a program, and I can't figure out why my progress bar won't become visible after the convert button is clicked.
private void convertButton_Click(object sender, EventArgs e)
{
toolStripProgressBar.Visible = true;
...
toolStripProgressBar.Visible = false;
}
I ran into a similar problem with tkinter in Python, and I had to call a function to update the idle tasks. Is there a way to do this with windows forms without using threads?
Edit: On a side note, this is a progress bar in a toolStrip that also contains a label that gets updated with status bar text. Is there any way to get the label on the left side and the progress bar on the other instead of right next to each other on the left?
Well, there is a way to do this without using threads (Application.DoEvents) but I strongly recommend against you using it. Re-entrancy is nasty, and you really don't want the UI thread tied up at all.
Use BackgroundWorker instead - it's easy, and it's pretty much designed for progress bars. It takes the hassle out of using a separate thread and reporting progress back to the UI thread. No need for Control.Invoke etc - it takes care of that for you.
There are lots of tutorials for BackgroundWorker - it shouldn't take you too long to get going with it.
Per the question you asked for the way to do this WITHOUT threads, that is to do it with Application.DoEvents();. (Just add that call right after setting the progress bar as visible.)
Now I do agree with Jon Skeet though that BackgroundWorker is a better way of doing this, but it does use a separate thread.
You need to execute your process in a thread separate from the UI thread, and then have it periodically report back to the UI thread with it's progress. If your convert operation is working inside the UI thread, it will simply go unresponsive until the operation is complete.
The progress bar can only become visible when it is allowed to paint which occurs during the processing of messages. Message processing cannot normally happen while you are in the middle of an event handler. If you want the progress bar to show up you will have to set the visiblitity to true, start a background thread to complete the work and return from the handler.
I'm guessing the problem is that the "..." in your code is a long-running process. UI updates are not instantaneous, but must run through the message queue in windows and then be painted to the screen. The queue is pumped and painting takes place in the same thread as your events.
As a result, any long-running tasks need to be moved to a different thread. More than that, your line line of code needs to called after that thread terminates. Otherwise you set the progress bar and then immediately turn it off again.
One way to do that is with a BackgroundWorker control.
Here go two links trying to explain you how things work:
(1) (2)
Now, I will try to explain it as shortly as I can. Most of what happens inside a windows forms application happens in a single thread, usually the same thread Main() runs in. If you open Program.cs, you will see that Main() has a line that looks like the following:
Application.Run(new Form1());
If you debug the application at any moment and examine the call stack, you will see it will trace back to that Run method. This means that a Windows Forms application is in fact a continuous run of the Run method. So, what is Run doing? Run is eating a message queue through which Windows sends messages to it. Run then dispatches those messages to the correct controls, which themselves do things like add text which corresponds to the key being pressed, redraw themselves, etc. Notice that all this happens during and endless loop running alongside a single thread, so weather you are typing or simply moving the window around, loads of those messages are being passed onto the application, which in turn is processing them and reacting accordingly, all in that single thread. Controls can also send messages to themselves through the queue and even you can place messages in the pump via Control.BeginInvoke. One of the things those controls do is to raise events according to what happens. So, if you click a button, the code you've written to handle that click will ultimately and indirectly be run by the Application.Run method.
Now, what is happening with your code is that even though you are changing the visible status of your progress bar to visible and then updating its Value, you are then changing its visibility to false, all in the same method. This means that only after you leave the method, will Application.Run() be able to continue iterating and consuming the message queue, effectively asking the progress bar to update its display. When that happens, you've already left the progress bar's visibility to false, the last thing you did before exiting the method. DoEvents() is a quick and dirty workaround to your problem as it reads the messages in the queue and processes them. I don't really feel comfortable using it as it can bring reentrancy problems.
Using threads is a good solution, but I would recommend using a ThreadPool thread instead of a custom thread in this kind of situation, as I tend to use custom threads only in cases where I have a limited number of long lived threads and I need to control their life cycles. The easiest and most practical way to use threads is to use the BackgroundWorker component, even though I would recommend going through the pains of understanding how to do Windows Forms multithreading with delegates if you want to really understand what is going on.
My solution is to call refresh on the status strip.
I believe this causes the UI thread to repaint the status strip.
toolStripStatusBar1.PerformStep();
statusStrip1.Refresh();
This is for .NET 4.0. Even though this question is old it was the first I found on googling this issue.

Categories

Resources