Multiple windows, multiple threads. Setting window owner - c#

I’ve created a window in WPF to display the status of the currently running operation.
The window is run on a separate thread, derived from this: Multiple Windows, Multiple Threads example.
The first thing I did was to set the Owner of my status window, since I want it to be displayed at the parent owner. It should be minimized together and not hidden behind the owner. I have used WindowInteropHelper to set the owner.
And here is the problem: while the main thread is busy, and not reporting any progress for a while, the status display window stops responding as well. How can I keep the child window responsive while its owner is busy?

It sounds like your doing all over your heavy work on the UI thread. You need to off load this to a new thread then call back to the UI thread with updates to your status window. This will ensure that your status bar remains responsive while the work is being done in the background.
There is an example for this in the section above the windows example in the link you provided.
See Handling blocking operations
If you want something like a progress bar you will need to decide at which stage to advance the bar instead of just knowing when everything is complete.

Related

C# WPF Multithreading with real-time PLC

I have an application that monitors bit states from external socket/Ethernet connections, known as a PLC device.
These states trigger database calls and UI updates, some of which require Modal dialogs, others require Modeless dialogs.
The issue is that the process needs to continually monitor even when a Modal dialog is displayed.
I have tried using a DispatcherTimer, but this will block when a Modal dialog is displayed. I understand the reason why.
I tried a standard Timer, but I get an exception stating something like 'Some UI components require the thread to run in STA mode.'
So I create a standard Thread and set the ApartmetState to STA. The thread runs just fine after adding DispatcherInvoke around the part of the processing loop that requires UI interaction, but whenever a Modal dialog box is displayed, the thread is blocked until the Modal dialog is closed.
Now I really do not want to get into inter-thread messaging and over-complicating the whole thing.
I have also tried putting the Modal dialog into its own thread whenever a Modal dialog is needed. Everything works fine and it was almost acceptable, but the owner window of the application is still accessible, essentially making the Modal dialog a Modeless dialog. I tried setting the IsEnabled flag on the owner window and at first I thought that would be okay, but it is still active when clicked and hides the dialog.
Any suggestions?
I have solved the issue! I reverted back to a standard Timer and was able to get around not requiring STA mode; this reguired another judicial placement of Dispatcher.Invoke.
Now everything works as I expect.

showing status bar first to show progress

Im creating a c# windows form and ive come accross a problem.
When the window opens I am wanting to run a bit of code which can make the front console appear to freeze. The code runs fine but I want to show the status of the program in the status strip at the bottom of the page. I am running the code in the action Form.Shown. However the code does not update the status bar until everything is shown. I can change the label no problem.
How would I go about loading the window and then running the code and updating the status bar (like a background task)?
What areas would I need to look at to get this information?
You could use a BackgroundWorker to do this
Set the WorkerReportsProgress property to true and in the DoWork eventhandler raise the ReportProgress event
in the eventhandler for the ProgressChanged place your logic to update your progresbar
there is a example on msdn
You can use Multithreading to avoid freezing the forms. It means, you separate your form and the code (that you want to run in parallel) in different threads so that the form doesn't wait for the code completes. You can monitor the progress of the code via events.

Cross-threading error/ Unresponsive UI

I have a WPF application in which I have a MainWindow under UI thread. I have created a thread in which I create another window. I have to create this window in a thread because it has to be updated continuously. I want the owner of this window to be the MainWindow. So I am using Dispatcher.Invoke to set the owner of this window.
But when I use Dispatcher.Invoke to access Main UI Thread from Thread 2, I get a cross thread access exception.
I'll post some sample code very soon. Until then, if someone has any idea, please share it.
This is my actual problem to which I thought of implementing above mentioned approach:
I have three line charts with 4 line series each in a window which are updated at an interval of 100 ms which I am doing using Dispatcher.Invoke. Because of this, the UI becomes kind of slow and unresponsive sometimes
I have created a thread in which I create another window.
That already isn't a very good idea and is prone to a lot of problems. All windows in your application should be created by the main "GUI" thread.
I have to create this window in a thread because it has to be updated continuously.
There are ways to achieve that without creating the window on another thread. Create your window on the main thread, then use a background thread to update it. That background thread can update your new window by using Dispatcher.Invoke.

Background work that perform UI change and modal dialog

I have a C#/WPF application that is going to perform a lot of actions, including UI modifications (it is loading a Macro), but I want to have a modal window with something moving telling to wait.
The load macro work must be performed in the main application thread, but how to I print the modal window as it must be non blocked by the macro loading but in the application thread because it is a UI thing.
Currently I put the LoadMacro in an BackgroundWorker in a Application.Current.Dispatcher.Invoke while displaying my waiting dialog. But it is not satisfying because the two fight each other to update the UI.
So how do I do it ?
You don't need to run the background worker from any dispatcher.
Load your modal window and then kick off the background worker having subscribed to it's ProgressChanged event. You can then ReportProgress on the background worker passing anything you like back to update the model window in the UserState property.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.progresschanged.aspx

Windows Forms: Progress Bar Unresponsive

I have a small application to convert several file formats, with a main windows form which contains several text boxes, buttons, etc. I have another "Document" class which handles all of the actual conversion work, and my form essentially iterates through all of the files, and calls the proper Document methods to convert the files. While this is happening, however, the form stops responding. I created another simple form with a progress bar and a cancel button to spawn when the conversion starts to provide some feedback to our (easily rattled) users. When the new form loads, however, all of the controls are white boxes, and it too stops responding. Once the conversion completes, the progress bar closes properly, and the main form becomes responsive again.
Is there a simple way to make these two forms independent, so that the progress bar can operate even while the other form is unresponsive?
The simplest solution is to have your processing done on a background thread using the BackgroundWorker component. You can drag it in from the VS toolbox. It allows you to update the UI thread with progress notifications so you can update your progress bar to show realistic values (something much more user-friendly than having a "marquee" style progress bar).
You should use two threads so that the form continues to respond while you do work.
This is so common that .NET has a BackgroundWorker control that wraps some of this up for you.
Just call Application.DoEvent() once in a while, probably in your loop.
Not as right as BackgroundWorker, but it's even simpler.
The simplest solution is to have your processing done on a background thread using the BackgroundWorker component. You can drag it in from the VS toolbox. It allows you to update the UI thread with progress notifications so you can update your progress bar to show realistic values (something much more user-friendly than having a "marquee" style progress bar).

Categories