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.
Related
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.
I have a big winform application that takes long time to load so I wrote a splash screen for it.
The problem is that when I show the splash form from a new thread, the progress bar will freeze 2 or 3 times while loading. But when I do it using a separated process I haven't any problem and it has a smooth motion.
I want to know that what's the difference between a new thread and a separated process in such a situation.
Thanks
Simply think of it as the Main form has it's own thread. When you are doing something on that thread that is task intensive, it doesn't get a chance to update the UI. However, when you create a new thread, you are in effect creating a new worker that can update the splash screen UI, while the Main form's thread is performing its workload.
A process is an executing instance of an application. For example, when you double-click the Microsoft Word icon, you start a process that runs Word. A thread is a path of execution within a process. Also, a process can contain multiple threads. When you start Word, the operating system creates a process and begins executing the primary thread of that process.
Another difference between a thread and a process is that threads within the same process share the same address space, whereas different processes do not.
It could be because the UI for the splash screen needs to be in a completely separate thread from the main window with a totally separate Windows message queue.
To run some UI in a different thread from the main thread you will need to start a new message pump for it, because message queues cannot be shared between threads.
To start a new message pump, call Application.Run(yourSplashScreen); from the separate thread. Create your splash screen form from the separate thread too.
Note that you cannot directly manipulate controls in one form from code executing in a different form that you started in a separate thread. You would have to use Control.Invoke() to do so, just like you normally do with multiple threads.
Anyway, if you use a separate message queue like this it could help to prevent the stalling that you're seeing.
I have a very complex Window created with WPF.
Since it takes very long time to load (about 10s), I want to create the window in the background after startup of the application.
My Shell contains one button where this window will be used, when the User clicks on it. The idea is to load the application and this button is disabled. After loading, my complex will be created in the background. When the window is created, I can enable this button and the user can use it.
But it is very important, that the Application does not block, while the window will be created on the background. The user should be able to use other modules in this time.
Does somebody know a way to reach my goal?
Perhaps someone knows, if there are more possibilities to reach this goal in the next .NET-Framework 4.5?
You can create window in background thread. Things you need to pay attention to are:
Thread must be STA and should be background thread so it will be terminated if main application thread is terminated.
You must keep that background thread alive or you will loose your window.
When referencing other GUI elements you should use Dispatcher.Invoke or Dispatcher.BeginInvoke if that GUI element is from another thread.
Here's the example for creating window in background thread:
Thread thread = new Thread(() =>
{
Window windowInAnotherThread = new Window();
windowInAnotherThread.Show();
System.Windows.Threading.Dispatcher.Run();
}) { IsBackground = true };
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
Use the BackgroundWorker.
Note that you can not create the actual window in the BackgroundWorker. The window needs to be created on the UI thread. But you can load all necessary data in the BackgroundWorker and use that data from the form once it is loaded.
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
I want to create a new instance of a form in a BackgroundWorker. I've noticed that when I do this, the newly launched form freezes.
Why does this form freeze? How can I get around this?
It's freezing because you're creating the form in the wrong thread - there's no event loop running in the background thread.
You should only create or touch UI elements in the UI thread. BackgroundWorker provides some hooks for this, or you can use Control.Invoke/BeginInvoke.
When a form "runs" it needs to have a thread that runs the WndProc and handles incoming messages from Windows. What you should consider doing here is using the Application.Run() method to start up your form. This will do the necessary work to make sure the WndProc is running properly, and I belive you can call this from your Background thread if necessary.