Wpf BackgroundWorker WorkerReportsProgress ProgressChanged
<Window x:Class="WpfApp37.MainWindow" 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:WpfApp37" WindowState="Maximized" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid TextBlock.FontSize="16"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="6"> <TextBlock Text="From:"/> <TextBox Margin="10,2,2,2" Width="120" MaxLength="10" x:Name="_from"/> <TextBlock Text="To:" Margin="20,0,0,0"/> <TextBox Margin="10,2,2,2" Width="120" MaxLength="10" x:Name="_to"/> </StackPanel> <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="6"> <Button Content="Calculate" x:Name="_calcBtn" Padding="4" Click="calc_Click" /> <Button Content="Cancel" x:Name="_cancelBtn" Padding="4" Click="_cancelBtn_Click"/> </StackPanel> <ProgressBar x:Name="_progressBar" Grid.Row="2" Height="30" Margin="4"/> <TextBlock Grid.Row="3" x:Name="_result" FontSize="20" Margin="6" HorizontalAlignment="Center"/> </Grid> </Window> using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp37 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { BackgroundWorker _bgWorker; int _cnt = 0; int _oldValue = 0, _newValue = 0; Stopwatch sw = new Stopwatch(); public MainWindow() { InitializeComponent(); } private void calc_Click(object sender, RoutedEventArgs e) { _bgWorker = new BackgroundWorker(); _bgWorker.WorkerSupportsCancellation = true; _bgWorker.WorkerReportsProgress = true; _bgWorker.DoWork += _bgWorker_DoWork; _bgWorker.RunWorkerCompleted += _bgWorker_RunWorkerCompleted; _bgWorker.ProgressChanged += _bgWorker_ProgressChanged; _calcBtn.IsEnabled = false; _cancelBtn.IsEnabled = true; _result.Text = "Calculating..."; var data = new PrimeInputData() { First = UInt64.Parse(_from.Text), Last = UInt64.Parse(_to.Text) }; _bgWorker.RunWorkerAsync(data); } private void _bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { _progressBar.Value = e.ProgressPercentage; _result.Text = $"Calculating progress:{_progressBar.Value}%,prime count:{_cnt},now:{DateTime.Now.ToString("yyyyMMddHHmmssffff")},time cost :{(int)sw.Elapsed.TotalMilliseconds} milliseconds"; } private void _bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled) { _result.Text = $"Cancelled Primes:{_cnt},now:{DateTime.Now.ToString("yyyyMMddHHmmssffff")},cost:{(int)sw.Elapsed.TotalMilliseconds} milliseconds"; } else { _result.Text = $"Finished Total Primes:{e.Result},now:{DateTime.Now.ToString("yyyyMMddHHmmssffff")},cost:{(int)sw.Elapsed.TotalMilliseconds} milliseconds"; } _calcBtn.IsEnabled = true; _cancelBtn.IsEnabled = false; } private void _bgWorker_DoWork(object sender, DoWorkEventArgs e) { var data = e.Argument as PrimeInputData; sw.Restart(); if (data != null) { _bgWorker.ReportProgress(0); UInt64 range = data.Last - data.First + 1; UInt64 progressCount = 0; UInt64 interval = range / 100; for (UInt64 i = data.First; i <= data.Last; i++) { if (_bgWorker.CancellationPending) { e.Cancel = true; break; } UInt64 limit = (UInt64)Math.Sqrt(i); bool isPrime = true; for (UInt64 j = 2; j <= limit; j++) { if (i % j == 0) { isPrime = false; break; } } if (isPrime) { _cnt++; } if (++progressCount % interval == 0) { _bgWorker.ReportProgress((int)(progressCount * 100 / range)); //approximately total sleep 10 seconds,100*100millseconds=10seconds //Thread.Sleep(100); //approximately total sleep 1 seconds,100*10millseconds=1seconds //Thread.Sleep(10); } } if (!e.Cancel) { _bgWorker.ReportProgress(100); } e.Result = _cnt; } } private void _cancelBtn_Click(object sender, RoutedEventArgs e) { _bgWorker.CancelAsync(); _calcBtn.IsEnabled = true; _cancelBtn.IsEnabled = false; } } class PrimeInputData { public UInt64 First { get; set; } public UInt64 Last { get; set; } } }