0

A have a WPF application and sometimes I want to show a dialog that performs some heavy calculation so it takes several seconds to show it up.
To make it clear , I want to show a splash screen with a progress bar or a loader.

I have done the following so far :

var splash = new SplashWindow();
splash.Show();
var dialog = new HeavyWindow();
dialog.OnWindowShown += delegate () { splash.Close(); };
dialog.ShowDialog();

The WaitWindow is just a semitransparent Window with an animation based on Storyboard and ColorAnimationUsingKeyFrames.
I can provide the code if needed.

The HeavyWindow is a Window that performs some heavy operation and at end it calls OnWindowShown (binded to ContentRendered event) to close the splash screen.

The problem is that after creating the HeavyWindow the animation in SplashWindow stops.
I can understand this behavior since both windows are in the same GUI thread.
The only thing I can't understand is how I can move the SplashWindow into a separated thread. Is there any other solution to the issue?

LopDev
  • 823
  • 10
  • 26
folibis
  • 12,048
  • 6
  • 54
  • 97
  • maybe Task.Run will help you. – Arphile Jul 01 '20 at 06:37
  • AFAIK, there's only one UI thread - however, you can move all the heavy work in HeavyWindow's constructor to a task as @Arphile suggested - that should not block the UI thread. – Zohar Peled Jul 01 '20 at 06:45
  • I've update the code with `Window splash = null; Task taskA = new Task(() => { splash = new WaitWindow(); splash.ShowDialog(); }); taskA.Start();` but in this case the splash window not shown at all. A probably do something wrong. @Arphile, can you please correct me? – folibis Jul 01 '20 at 06:46
  • Just use var T = Task.Run( () => { ///TASKS/// }; T.Wait() if you wanna wait until task finished. – Arphile Jul 01 '20 at 06:48
  • if you need to use ShowDialog, Dispatcher.Invoke will help you. – Arphile Jul 01 '20 at 06:49
  • if not, jsut use Show() for that. – Arphile Jul 01 '20 at 06:49
  • Ideally, you should move the heavy work off the Main/GUI thread. However if you really want two GUI threads/Dispatchers, refer to [this](https://stackoverflow.com/questions/5716804/can-does-wpf-have-multiple-gui-threads) – Suresh Jul 01 '20 at 06:50
  • 4
    _" I want to show a dialog that performs some heavy calculation"_ - Just no! Use the Dialog for Display only. For computations use a Task + Progress/IProgress, to update the Dialog's UI Elements. Something along this: https://stackoverflow.com/a/29872887/982149 Or get it from the master himself Stephen Cleary: https://blog.stephencleary.com/2012/02/reporting-progress-from-async-tasks.html – Fildor Jul 01 '20 at 06:54
  • *"how can I move the SplashWindow into separated thread"* - create thread, run it and then inside that thread construct and show window. – Sinatr Jul 01 '20 at 06:57
  • Maybe we all think in a wrong direction and this is what you want? - [how to add a splash screen to a wpf application](https://learn.microsoft.com/en-us/dotnet/framework/wpf/app-development/how-to-add-a-splash-screen-to-a-wpf-application) and further: https://learn.microsoft.com/en-us/dotnet/api/system.windows.splashscreen?view=netcore-3.1 – Fildor Jul 01 '20 at 07:00
  • ^^ Ah, no. Forget it. They can only show images... :( – Fildor Jul 01 '20 at 07:04
  • 2
    @Arphile Why would you want to spawn a task via `Task.Run()` only to `Wait()` it? –  Jul 01 '20 at 07:26
  • 2
    @Arphile Never use `Dispatcher.Invoke`. It will lead to a GUI thread lock-up. Use `BeginInvoke` –  Jul 01 '20 at 07:27
  • 1
    The only solution that works here is to move the "heavy job" on a separated thread (Task, Thread, BackgroundWorker, whatever) otherwise the UI will still stuck. WPF has just 1 thread delegate to render the UI (the Dispatcher thread) so creating a thread to render the window will not boost your solution because the "other thread" needs to synchronize with the unique Dispatcher thread. – trix Jul 01 '20 at 07:28
  • 1
    @Sinatr _"create thread, ... inside that thread construct and show window"_ - ensure the thead is a STA thread of course –  Jul 01 '20 at 07:28
  • If you were to use MvvM you would have had a task in your view model that would do "heavy work" in the background and then just flip a bool property which would trigger a ContentControl to be shown with animation, job done. Why do you insist on making this hard work for yourself? That approach maybe worked with WinForms, WPF is much more sophisticated. – XAMlMAX Jul 01 '20 at 09:52

0 Answers0