How to show animation when creating a custom control

In a WPF 4 application, I have a very large user control full of controls, which for something like 4s is initialized on a fast machine. During this time, the application, of course, does not respond at all.
Is there a way to show the animation in the main window while this control is initialized?

I understand that I cannot create it in another thread. But could there be a way to create it with a lower priority from the Dispatcher so that I can show the spinning wheel or so in the main window that will spin anyway?

(The only solution I can think of now is to split user control into other parts and load them only when necessary, but this will take a lot of development time.)

Update1
To be more clear: this is a simple bookmarked WPF window. When a new tab opens, I initialize the user control that contains the controls for this bookmark. One of these user controls is so full of controls that it takes 4 seconds until a new page is displayed. So I thought that showing a spinning wheel would be better than having a locked application.

+4
source share
3 answers

I think you will have to break this user control into pieces. You can use BackgroundWorker to coordinate the "build" of this user control. Each time a DoWork event is fired, use Dispatcher.BeginInvoke to create an additional control for your user interface. This method is described in the following blog post:

http://loekvandenouweland.com/index.php/2010/12/wp7-add-user-controls-graphics-in-background-thread/

This will allow you to show animations at boot time.

+5
source

Why can't you initialize it in another thread? I see two scenarios:

  • Initialization is slow for reasons other than WPF, which are preloaded / precomputed in another thread before initiating initialization of the main WPF.
  • WPF itself consumes 4 seconds of processor time (although these are really WTF processor time levels ...). If so, you can start another STA stream using your own message pump, which can display an independent user interface (such as a spinning wheel) until the main thread is loaded.

You can create β€œdialogs” that implicitly create a new dispatcher and run in the background thread, or you can explicitly create your own dispatcher (= message).

To do this, I use the following method:

public static Dispatcher StartNewDispatcher(ThreadPriority cpuPriority = ThreadPriority.Normal) { using (var sem = new SemaphoreSlim(0)) { Dispatcher retval = null; var winThread = new Thread(() => { retval = Dispatcher.CurrentDispatcher; sem.Release(); Dispatcher.Run(); }) { IsBackground = true, Priority = cpuPriority }; winThread.SetApartmentState(ApartmentState.STA); winThread.Start(); sem.Wait(); return retval; } } 

This gives you a real multi-threaded interface; but it also means that you cannot communicate with the data or in any other way directly interact between the two user interfaces: after all, WPF objects are thread bound.

Before you go this route, check to see if there are any slow components that you can preload using the profiler: option 1 (preloading heavy material before WPF init) is easier and cleaner.

+2
source

The solution could be to move the slow part (loading data? Which is not part of the control) to another thread, as you mentioned.

Or use VirtualizingStackPanel to lazily load what you need.

Could you explain the reason for the delay?

0
source

Source: https://habr.com/ru/post/1337142/


All Articles