WPF IProgress CancallationToken
<Window x:Class="WpfApp180.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:WpfApp180" mc:Ignorable="d" WindowState="Maximized" Title="MainWindow" Height="450" Width="800"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <StackPanel 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 Orientation="Horizontal" Grid.Row="1" Margin="6"> <Button Content="Calculate" Padding="4" x:Name="calc" Margin="4" Click="calc_Click"/> <Button Content="Cancel" Padding="4" Margin="4" x:Name="cancel" IsEnabled="False" Click="cancel_Click"/> </StackPanel> <ProgressBar x:Name="progressBar" Grid.Row="2" Margin="4" Height="30"/> <TextBlock x:Name="result" Grid.Row="3" Margin="6" HorizontalAlignment="Center" FontSize="20"/> <TextBlock x:Name="progressTb" Grid.Row="4" Margin="6" HorizontalAlignment="Center" FontSize="20"/> </Grid> </Window> using System; using System.Collections.Generic; using System.Linq; 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 WpfApp180 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { CancellationTokenSource cts; public MainWindow() { InitializeComponent(); } async Task<int> CountPrimesAsync(int first,int last,CancellationToken ct, IProgress<double> progress) { var task = Task.Run(() => { int total = 0; int range = last - first + 1; int pCount = 0; for(int i=first;i<=last;i++) { ct.ThrowIfCancellationRequested(); bool isPrime = true; int limit = (int)Math.Sqrt(i); for(int j=2;j<=limit;j++) { if(i%j==0) { isPrime = false; break; } } if(isPrime) { total++; } if(++pCount%1000==0) { double progValue = pCount * 100 / range; progress.Report(progValue); Dispatcher.BeginInvoke(new Action(() => { progressTb.Text=$"{progValue.ToString()}%"; })); } } return total; }); return await task; } private async void calc_Click(object sender, RoutedEventArgs e) { int first = int.Parse(_from.Text); int last=int.Parse(_to.Text); cts = new CancellationTokenSource(); calc.IsEnabled = false; cancel.IsEnabled = true; result.Text = "Calculating..."; var prog = new Progress<double>(x => progressBar.Value = x); try { int count = await CountPrimesAsync(first, last, cts.Token, prog); result.Text = "Total Primes:" + count; } catch (OperationCanceledException ex) { result.Text = "Operation cancelled!"; } finally { cts.Dispose(); calc.IsEnabled = true; cancel.IsEnabled = false; } } private void cancel_Click(object sender, RoutedEventArgs e) { cts.Cancel(); cts = null; } } }