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 ?
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.
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.