1

Here is the code that instantiate a window with an indeterminate progress bar, this code is called in a viewmdodel of some view :

Views.InstallingWindow installing = new Views.InstallingWindow(); installing.Show(); Application.Current.Dispatcher.Invoke(timeConsumingMethod, DispatcherPriority.Normal); installing.Close(); 

And here is the xaml of the window

<Window x:Class="Blabla.Views.InstallingWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:PatcherClient.Views" mc:Ignorable="d" Title="InstallingWindow" Height="150" Width="300" WindowStartupLocation="CenterScreen"> <Grid> <StackPanel Margin="10"> <ProgressBar Width="200" Height="20" Margin="10" Orientation="Horizontal" IsIndeterminate="True" /> <TextBlock HorizontalAlignment="Center" Name="StatusText" Margin="10" Height="50" Foreground="Black" Text="Installing ..."/> </StackPanel> </Grid> 

On my computer, the progress bar does not animate. How to fix it ?

3
  • 1
    You can't execute timeConsumingMethod on the UI thread if you want it to be able to animate the ProgressBar. Commented Jun 27, 2017 at 12:40
  • Running long time consuming methods is not what the dispatcher is for, possibly related: stackoverflow.com/questions/1644079/… Commented Jun 27, 2017 at 12:40
  • Use BeginInvoke instead. Commented Jun 27, 2017 at 12:44

2 Answers 2

4

Dispatcher.Invoke executes your timeConsumingMethod delegate on the UI thread so it will be blocked.

Try this instead in an async method:

installing.Show(); await Task.Run(() => timeConsumingMethod()); installing.Close(); 

If your timeConsumingMethod accesses any UI component (eg. sets control properties), then you should wrap these accesses into Dispatcher.Invoke only.

Sign up to request clarification or add additional context in comments.

Comments

3

This will execute timeConsumingMethod on the dispatcher thread:

Application.Current.Dispatcher.Invoke(timeConsumingMethod, DispatcherPriority.Normal); 

And the dispatcher cannot both execute your method and animate the ProgressBar simultaneously.

You want to execute timeConsumingMethod on a background thread. The easiest way to do this is to start a new Task and then close the window once the task has completed:

Views.InstallingWindow installing = new Views.InstallingWindow(); installing.Show(); System.Threading.Tasks.Task.Factory.StartNew(() => { timeConsumingMethod(); }).ContinueWith(task => { installing.Close(); }, System.Threading.CancellationToken.None, System.Threading.Tasks.TaskContinuationOptions.None, 

System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext());

Note that for this to work, you cannot access any UIElement in your timeConsumingMethod() method. A UIElement may only be accessed on the UI thread on which it was originally created.

1 Comment

thanks for this fast answer ! Because I use .Net 3.5 i worked out a solution using method.BeginInvoke(), and in the callback I use the Dispatcher to close the window. Actually, I had not noticed that the Dispatcher is for the UI objects, which is what everybody pointed out...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.