之前使用线程池来进行异步计算,示例如下所示:
WPF从非UI线程中更新UI元素
WPF取消一个线程的执行
此文章还使用了BackgroundWorker 中的进度条事件,效果如下所示:
点击取消按钮后,效果如下所示:
XAML布局如下所示:
<StackPanel>
<StackPanel Orientation="Horizontal">
<Border
Margin="10"
BorderBrush="Black"
BorderThickness="1">
<TextBlock Margin="10" Text="开始数字:1" />
</Border>
<Border
Margin="10"
BorderBrush="Black"
BorderThickness="1">
<TextBlock Margin="10" Text="结束数字:1000000000" />
</Border>
</StackPanel>
<StackPanel>
<Border
Margin="10"
BorderBrush="Black"
BorderThickness="1">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="10" Text="奇数个数:" />
<TextBox
x:Name="jsValue"
Width="Auto"
Height="20"
Text="0" />
</StackPanel>
</Border>
<Border
Margin="10"
BorderBrush="Black"
BorderThickness="1">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="10" Text="偶数个数:" />
<TextBox
x:Name="esValue"
Width="Auto"
Height="20"
Text="0" />
</StackPanel>
</Border>
</StackPanel>
<ProgressBar
x:Name="progressBar"
Height="30"
Margin="10" />
<StackPanel>
<Button
x:Name="btn"
Width="120"
Height="30"
Margin="20"
Click="Button_Click"
Content="开始计算" />
<Button
Width="120"
Height="30"
Margin="20"
Click="Button_Click1"
Content="取消计算" />
</StackPanel>
</StackPanel>
隐藏代码如下所示:
using System;
using System.ComponentModel;
using System.Windows;
namespace TheadPoolDemo
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Calculator(int from, int to)
{
tmpJsValue = 0;
tmpEsValue = 0;
Int32 interation = (to - from) / 100; // 间隔多少
for (Int32 i = from; i < to; i++)
{
// 判断是否请求取消
if (worker.CancellationPending)
{
return;
}
if (i % 2 == 0) ++tmpEsValue;
else ++tmpJsValue;
if ((i % interation == 0) && (worker != null) && (worker.WorkerReportsProgress == true))
{
worker.ReportProgress(i / interation);
}
}
}
Int32 tmpJsValue = 0;
Int32 tmpEsValue = 0;
BackgroundWorker worker = null;
private void Button_Click(object sender, RoutedEventArgs e)
{
this.btn.IsEnabled = false;
this.esValue.Text = "0";
this.jsValue.Text = "0";
worker = new BackgroundWorker();
worker.WorkerSupportsCancellation = true; // 支持异步取消操作
worker.WorkerReportsProgress = true; // 允许报告进度更新事件
worker.ProgressChanged += Worker_ProgressChanged; // 调用 reportprogress 时发生
worker.DoWork += Worker_DoWork; // 需要做的事情
worker.RunWorkerCompleted += Worker_RunWorkerCompleted; // 操作完成之后需要干的事情
worker.RunWorkerAsync(new Tuple<Int32, Int32>(1, 1000000000)); // 开始操作,调用 DoWork
}
private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar.Value = e.ProgressPercentage; // 传入的值
}
private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// 操作完成之后,注销事件,并且显示数据
if (sender is BackgroundWorker worker)
{
// 判断是否已经取消操作成功了
if (e.Cancelled == true)
{
this.jsValue.Text = "取消成功!";
this.esValue.Text = "取消成功!";
}
else
{
this.jsValue.Text = tmpJsValue.ToString();
this.esValue.Text = tmpEsValue.ToString();
}
worker.DoWork -= Worker_DoWork;
worker.RunWorkerCompleted -= Worker_RunWorkerCompleted;
worker = null;
}
this.btn.IsEnabled = true;
this.progressBar.Value = 0;
}
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
// 需要做的事情:计算奇偶数
var args = (Tuple<Int32, Int32>)e.Argument;
Calculator(args.Item1, args.Item2);
if (worker.CancellationPending) // 判断是否请求取消
{
e.Cancel = true; // 取消该事件 响应上面的操作
}
}
private void Button_Click1(object sender, RoutedEventArgs e)
{
worker.CancelAsync(); // 请求取消
}
}
}