Creating complex WPF-Window in Background - c#

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.

Related

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.

Multiple windows, multiple threads. Setting window owner

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.

C# splash screen using a new thread

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.

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

WPF Get UI Thread, or how to show a window from NON-UI Thread

I realized a WPF Control Library to use as an Addin in MS Office 2007.
The WPF-Class is instantiated by the host and creates a toolbar with some buttons in MS Office.
By clicking a button the WPF window should appear.
The problem is that I always receive the following error: "The calling thread must be STA, because many UI components require this."
My main function is marked as [STAThread].
It seems that the button_Click event runs in an other thread than the UI thread.
I tried to use a dispatcher, but that didn't work.
Dispatcher.CurrentDispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action(
delegate()
{
wpfform wf = new wpfform();
wf.ShowDialog();
));
I think the module gets a wrong dispatcher, but I don't know exactly.
Next I tried to start the window in an separate STA thread and join the thread, but this didn't work either. As I removed the [STAThread] Attribute from the main function the window started, but i was unable to access office (because i'm in a separate thread).
Thread workerThread = new Thread(_ShowDialog);
workerThread.SetApartmentState(ApartmentState.STA);
workerThread.Start();
workerThread.Join();
Is it possible to determine the UI thread and create a dispatcher for this thread, or how can I come back to the UI thread?
You will need to use the application UI dispatcher. Try using:
Application.Current.Dispatcher.Invoke(...)
You can use SynchronizationContext, which is described here in stackoverflow: Using SynchronizationContext for sending events back to the UI for WinForms or WPF (you have to "capture" context on UI thread, sadly, result of that question is: you should use Application.Current.Dispatcher -- maybe you should look why is null)

Categories