I am using the following code in WPF application to show progress bar:
XAML:
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Button Grid.Row="1" x:Name="btn_StartLengthyTask" Click="btn_StartLengthyTask_Click" Width="200" Height="30" >Start Lengthy Task</Button>
<ProgressBar Grid.Row="2" x:Name="pb_LengthyTaskProgress" Margin="10,20" Value="0" ></ProgressBar>
<TextBlock Grid.Row="3" x:Name="lbl_CountDownTimer" HorizontalAlignment="Center" > 00:10</TextBlock>
<TextBlock Grid.Row="4" x:Name="lbl_TaskStatus" >Status...</TextBlock>
C#:
private void btn_StartLengthyTask_Click(object sender, RoutedEventArgs e)
{
try
{
lbl_TaskStatus.Text = "Starting long Task...";
Thread.Sleep(1000);
lbl_TaskStatus.Text = "In Progress...";
pb_LengthyTaskProgress.Value = 0;
Task.Run(() =>
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(50);
this.Dispatcher.Invoke(() => //Use Dispather to Update UI Immediately
{
var test = OMS.MyOrders.Model.MyOrderExecutor.ExportImages(true);//Method taking long time to response
pb_LengthyTaskProgress.Value = i;
lbl_CountDownTimer.Text = i.ToString();
});
}
});
}
catch (Exception ex)
{
throw ex;
}
}
Problem: Progress bar is not updating on UI. Thanks in advance
Never call Thread.Sleep
. Either use a DispatcherTimer, or an async
Click event handler that calls await Task.Delay(...)
in a loop. Dispatcher.Invoke
is not needed. Wrap the long running method in an awaited Task.Run
call.
private async void btn_StartLengthyTask_Click(object sender, RoutedEventArgs e)
{
lbl_TaskStatus.Text = "Starting long Task...";
await Task.Delay(1000);
lbl_TaskStatus.Text = "In Progress...";
pb_LengthyTaskProgress.Value = 0;
for (int i = 1; i <= 100; i++)
{
await Task.Delay(50);
var test = await Task.Run(() =>
OMS.MyOrders.Model.MyOrderExecutor.ExportImages(true));
pb_LengthyTaskProgress.Value = i;
lbl_CountDownTimer.Text = i.ToString();
}
}
Update: it seems you only want make a single call to a long running method. The method should then report progress via the IProgress
interface:
public bool ExportImages(bool b, IProgress<double> p)
{
// call p.Report
}
It would be used like this:
private async void btn_StartLengthyTask_Click(object sender, RoutedEventArgs e)
{
lbl_TaskStatus.Text = "Starting long Task...";
await Task.Delay(1000);
lbl_TaskStatus.Text = "In Progress...";
var progress = new Progress<double>();
progress.ProgressChanged += (s, p) =>
{
pb_LengthyTaskProgress.Value = p;
lbl_CountDownTimer.Text = p.ToString();
};
var result = await Task.Run(() =>
OMS.MyOrders.Model.MyOrderExecutor.ExportImages(true, progress));
}