Reputation: 6279
I have a WPF Window which takes a lot of time to create and show. The user should be able to open one ore more of this windows. Now, I am searching a way to improve the performance. One Idea is to create two of this Windows at the startup of the Application (when It shows the splash-screen). After I have only to show and hide this windows (and change the attached viewmodel). This should not be a problem. But when the user is working with the application and he uses the two windows which are loaded at startup of the application, I should load a third instance of the window in background. Now, the application should no be blocked when It loads the third one (or the 4. oder 5. etc.). Now, I am searching a way to do this. Would it be possible to load the window in another thread and after transfer it to the main UI thread? Or are there other scenarios to reach the goal?
Thanks for any help.
Best Regards, Thomas
Upvotes: 3
Views: 7378
Reputation: 7282
I had a secondary wpf window that took a long time (2 seconds) to open first time it was displayed and very little time on subsequent loads. It turned out to be due to the extended toolkit assembly being loaded (and a couple other ones as well). To fix it I added the following to my App.xaml.cs:
var thread = new Thread(() =>
{//Force runtime to pre-load all resources for secondary windows so they will load as fast as possible
new SecondaryForm1();
new SecondaryForm2();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Priority = ThreadPriority.Lowest;//We don't want prefetching to delay showing of primary window
thread.Start();
//Now start primary window
After that change, the secondary windows would do first time display in about 10ms. I didn't like the look of the redundant instantiations at first, but really.. what's the harm? There are lots of other things that could delay the display of new windows, but this is certainly worth checking out. I got the idea from this question.
Upvotes: 8
Reputation: 97848
When you create a WPF object -- Window, UserControl, or anything else that descends from DispatcherObject -- it locks itself to the thread it was created on. So you can't load the window in a background thread and then transfer it to the main UI thread. If you're going to create it in a background thread, it needs to stay on that thread; it needs to be shown by that thread, and have a message pump on that thread.
But that's viable. You could start a background thread, create your window there, and then wait for the main thread to say, "Okay, it's time to show the window". Then your thread could call Application.Run to start its own message pump, and shut itself down when the window closes.
Of course, multithreading opens up all kinds of new complications. You probably need a dedicated thread for each window (the thread pool isn't likely to work for this). You need to handle all the inter-thread communication. If the windows access any shared data, you need to protect it with some sort of locking. You need to make sure the application exits when it should (and if that means "when all the windows are closed", then you need to make sure you protect the "count of open windows" resource). There are probably other complications as well. Don't enter into this lightly.
Your best bet, as others have said, is to profile your code and try to address your performance problems first. But if you're convinced that you've done as much performance work as you can, multithreading and background loading could be an option to explore.
Upvotes: 5
Reputation: 5533
Keep an eye on what taras said. Generally, such technologies as winforms and wpf are fast enough in creating UI. When you see a slow interface, double-check your own code: Are you loading tens of thousands of rows (then use paging). Are you calling a slow method (call it asychronously) are you making many calls to the database or network? (bach the calls or put them on another thread)
Come back to what you currently try to do if you fail at anything similar to the above list.
Upvotes: 1
Reputation: 1179
If I were you I would start from profiling your application to see what's really taking time during window start. As you have been told there is no way to create GUI in other thread and use it in main thread then, but if you have any statistics we can try to figure out what other things can be paralleled or cached.
Upvotes: 1
Reputation: 8254
Maybe you are trying to solve the problem from a wrong side? I think you should do long-running operations that causes windows to hang in a background, instead of trying to run windows in background. You can show window for users immediately and then show some nice animation while background threads do their work by retrieving data/calculating something/etc . Maybe I misunderstood your question
Upvotes: 4
Reputation: 311
I don't think that's possible, as WPF applications have one-and-only one UI thread.
Is it the GUI elements that are taking a while to load, or stuff in the VM? If it's stuff in the VM you could try to create the VM on another thread and bring it in...
Upvotes: 1