Progress reporting to parent UI thread - c#

apologies if I don't explain this clearly, but I'm writing an app which is causing me some problems with threading.
I have a UI which starts a System.Timers.Timer. Each time this timer elapses it triggers a workflow which opens a progress screen. To prevent another workflow starting before the last one has finished it locks an object on the main form.
This progress screen starts and reports the progress of, some file copying using FileCopyEX.
The problem I'm having is that the progress screen does not display until after the work flow has been completed.
Hopefully this will make it clearer:
Main Form
|
Timer Elapses
|
WorkFlow Starts
|
Progress Screen opens (errors which occur go back to the previous)
|
File copying occurs (progress reported back to progress screen)
If no errors, returns to main screen before next tick.
Until now I've only implemented very simple threading, so I'm not sure how best to implement this. I've tried starting the workflow on a BackGroundWorker to seperate it from the UI thread but it behaves the same.
Thanks

I suggest that you read about the BackgroundWorker. This has hooks for reporting progress.
Remember that system timers invoke its event handler on a non-UI thread. Whenever, you do something with the UI you must be on the UI thread.

Without the code I can only guess at the cause, but the likely reason is that the Progress window needs the UI to be pumping messages to appear - i.e. the UI thread needs to be running.
If the UI thread is busy running your workflow, then it won't get around to processing the displaying of your window until after that. You need to separate your flow so that the progress window is on your UI thread and the workflow is on a background thread.
Hope that makes sense!

Related

Execute code during winform progress bar running

I have a small winform application and i put a progress bar on first running form. This progress bar completes in 10 seconds and after progress bar completes the next activity starts like database call.
I want when this progress bar runs for 10 seconds, during this time database call should do its work instead of calling after the progress bar completes.
Can anyone explain or have sample code to explain this technique ???
Thanks in advance.
Your issue probably arises from the fact that you are running the heavy duty work on the User Interface Thread, so basically you are holding that thread from doing anything.
To solve this issue you need to run on a separate Thread and Control.Invoke the progress bar control when it needs update.
Check out Threading and the UI on VS Magazine.
You need to use a background worker!
Do your heavy operation in the background worker thread and on the UI thread keep the progress bar running.
You should find plenty of examples about the usage of a background worker, some here:
http://www.dotnetperls.com/backgroundworker
https://stackoverflow.com/a/15153258/2243584
There are many good multi-threading tutorials out there that explain in ample detail this question. Googling "winforms thread sync" this is the first one that comes up. Pretty good.

C# WinForms :- Why Thread Timer tick event not elapsed when UI is doing some other operation?

In my application UI, I am updating one of grid through Windows Timer tick every 1 sec.
It's not working properly when I am doing some other UI operations belongs to another windows forms(this is basically using tabbed forms)
I added trace for Timer_Tick event and logged in to file.
We found there is an missing of log data, when another UI operation going on (Open and closing of another windows form). Timer_Tick not hitting at this time.
Any suggestions...?
The issue is that the UI is running in a single thread. Any long-running blocking operation on that thread - like opening a form, running some code in response to a button click, etc - will prevent the timer from firing. This is the nature of single-threaded programming.
If you absolutely need to run code every second, regardless of what is happening in the UI thread, you'll need to use a second thread.
Related Links:
System.Threading.Thread documentation
System.Threading.Tasks.Task documentation
System.Threading.Timer documentation
And very important, for interacting with your UI from any of the above:
System.Windows.Forms.Control.Invoke method documentation
System.Windows.Forms.Control.InvokeRequired property documentation
The System.Windows.Forms.Timer tick event executes on the UI thread. If the UI thread is busy doing something else, then the timer tick handler will have to wait.
The tick events for System.Threading.Timer and System.Timers.Timer happen on threadpool threads, so they can execute while the UI thread is busy. If you need to update the UI from your tick handler, you can call BeginInvoke, and the UI update will happen when the UI thread is free.
There's no need to start a different thread or a BackgroundWorker that executes a Sleep loop.
You can run it on a BackgroundWorker since it just happens every 2 seconds without user interaction. For more details about BackgroundWorker, check this article "http://www.dotnetperls.com/backgroundworker" it's very easy to understand.
BackgroundWorker makes threads easy to implement in Windows Forms. Intensive tasks need to be done on another thread so the UI does not freeze. It is necessary to post messages and update the user interface when the task is done.

C# Window gets blank when busy -> Progressbar? But how?

I have a program which does some copy jobs (via File.Copy) that could last a few minutes. When the user brings another window to foreground in this time the program window gets blank since it doesn't redraw itself.
Now I want to show a ProgressBar in an extra window in the center of the screen, but that window get's blank too.
So I startet it in another thread which didn't help.
I'm quite sure someone did this before but I cannot find a working example. Any Ideas?
There is nice example in the documentation on BackgroundWorker class.
ChrisF is correct. Your long operation should be done in a BackgroundWorker thread. You can use BackgroundWorker to report progress, and hook that up to a progress bar on your form.
You need to thread your operation using a BackgroundWorker. There are other ways to thread the operation, but this one is probably the simplest, and will continue to perform message pumping in the foreground so Windows doesn't think your application has stopped responding.
Another option would be to use a Thread, and use Thread.Join to wait for the background task to complete, since Thread.Join also sends standard message pump information to Windows while it waits.
You can use BackgroundWorker class.
See this answer.

progress bar in separate window

(WPF) We have been asked to build a little window that pops up when the app is busy (instead of or in addition to a wait cursor). We put a textblock in the window, and a ProgressBar with IsIndeterminate = true.
We call show on the little window, and then start up our long-running process, calling Close on the little window when we are through. However, during the long-running process, the ProgressBar does not show any activity, and the little window shows (Not Responding) in its title.
Is this even possible? A better idea?
You need to look into using another thread (or multiple threads) to do the heavy processing that could take longer than 100ms (100ms and above can cause this 'hanging' appearence before 'Not Responding' appears.)
You could create a new thread using a BackgroundWorker
object and subscribe to the OnProgressChanged event to indicate a progress bar update. This does not however get around the problem of accessing the main (UI) threads Progress Bar. You would have to check if an Invoke is required and then invoke a piece of code responsible for updating the Progress Bar.
Here is a StackOverflow question that shows a nice Extension Method in the accepted answer for invoking a method call on a control:
Invoking
Hopefully that helps!!
The problem is most likely that whatever is causing the app to be "busy" is being run in the main thread of the app. So, the app stops responding, including responding to layout and painting requests from the OS. So, when the app is "busy", it's too busy to paint the new window.
The solution is to move as much "heavy lifting" as possible into background threads, so the main thread and thus the UI remain responsive.

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.

Categories

Resources