WPF BackgroundWorker 更新进度条
先看运行效果
在WPF 中如果直接在UI线程更新进度条,会造成界面卡死,因此使用BackgroundWorker来进行更新,既简单又方便。
先看xaml
1 <Window 2 x:Class="BackgroundWorker使用方法.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 xmlns:local="clr-namespace:BackgroundWorker使用方法" 7 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 8 Title="MainWindow" 9 Width="800" 10 Height="450" 11 mc:Ignorable="d"> 12 <Grid> 13 <StackPanel VerticalAlignment="Center" Orientation="Vertical"> 14 <TextBlock 15 x:Name="showText" 16 HorizontalAlignment="Center" 17 FontSize="30" /> 18 <Grid> 19 <ProgressBar 20 x:Name="bar" 21 Height="30" 22 Background="Green" /> 23 <TextBlock 24 HorizontalAlignment="Center" 25 VerticalAlignment="Center" 26 FontSize="20" 27 Text="{Binding ElementName=bar, Path=Value}" /> 28 </Grid> 29 <Grid Height="30" Margin="3"> 30 <Grid.ColumnDefinitions> 31 <ColumnDefinition Width="1*" /> 32 <ColumnDefinition Width="1*" /> 33 </Grid.ColumnDefinitions> 34 <Button 35 x:Name="start" 36 Grid.Column="0" 37 Margin="3,0" 38 Click="Start" 39 Content="启动" /> 40 <Button 41 x:Name="cancel" 42 IsEnabled="False" 43 Grid.Column="1" 44 Margin="3,0" 45 Click="Stop" 46 Content="取消" /> 47 </Grid> 48 </StackPanel> 49 </Grid> 50 </Window>
后台代码
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Linq; 5 using System.Text; 6 using System.Threading; 7 using System.Threading.Tasks; 8 using System.Windows; 9 using System.Windows.Controls; 10 using System.Windows.Data; 11 using System.Windows.Documents; 12 using System.Windows.Input; 13 using System.Windows.Media; 14 using System.Windows.Media.Imaging; 15 using System.Windows.Navigation; 16 using System.Windows.Shapes; 17 18 namespace BackgroundWorker使用方法 19 { 20 /// <summary> 21 /// 进度条参数 22 /// </summary> 23 public class BarState 24 { 25 private double _value; 26 27 /// <summary> 28 /// 进度条的颜色 也可以用渐变色来代替 29 /// </summary> 30 public Brush Color { get; set; } 31 32 /// <summary> 33 /// 提示文本 34 /// </summary> 35 public string ShowText { get; set; } 36 37 /// <summary> 38 /// 进度显示 39 /// </summary> 40 public double Value 41 { 42 get => _value; 43 44 set 45 { 46 if (value != _value) 47 { 48 OnValueChanged(this, new EventArgs());//触发事件 49 _value = value; 50 } 51 } 52 } 53 54 public BarState() 55 { 56 Color = new SolidColorBrush(Colors.Green); 57 Color.Opacity = 0.0; 58 ShowText = "还未启动"; 59 Value = 0; 60 } 61 62 /// <summary> 63 /// 进度显示事件 64 /// </summary> 65 public event EventHandler ValueChanged; 66 67 public void OnValueChanged(object sender, EventArgs e) 68 { 69 ValueChanged?.Invoke(this, e); 70 Color.Opacity = Value / 100; 71 if (Value <= 5) 72 { 73 ShowText = "启动中。。。"; 74 } 75 else if (Value <= 75) 76 { 77 ShowText = "运行中。。。"; 78 } 79 else if (Value <= 95) 80 { 81 ShowText = "即将完成。。。"; 82 } 83 else 84 { 85 ShowText = "已完成!"; 86 } 87 } 88 } 89 90 /// <summary> 91 /// MainWindow.xaml 的交互逻辑 92 /// </summary> 93 public partial class MainWindow : Window 94 { 95 private BackgroundWorker _worker; 96 97 private Brush barColor; 98 99 public MainWindow() 100 { 101 InitializeComponent(); 102 barColor = new SolidColorBrush(Colors.Green); 103 bar.Background = barColor; 104 _worker = new BackgroundWorker(); 105 _worker.WorkerReportsProgress = true;//获取或设置一个值,该值指示能否报告进度更新 106 _worker.WorkerSupportsCancellation = true;//获取或设置一个值,该值指示是否支持异步取消 107 108 _worker.DoWork += DoSomething;//挂载要运行的方法 109 _worker.ProgressChanged += ChangeValue;//挂载进度值改变的方法 110 _worker.RunWorkerCompleted += Complete;//当方法完成时候 111 } 112 113 private void ChangeValue(object sender, ProgressChangedEventArgs e) 114 { 115 var state = e.UserState as BarState; 116 bar.Value = state.Value; 117 118 //bar.Background.Opacity = state.Value / 100;//此处不能直接更改背景颜色,因为是依赖属性,此处只做演示,实际应在xaml中用动画 119 barColor.Opacity = bar.Value / 100; 120 showText.Text = state.ShowText; 121 } 122 123 private void Complete(object sender, RunWorkerCompletedEventArgs e) 124 { 125 if (e.Error != null)//如果发生异常 126 { 127 MessageBox.Show(e.Error.Message); 128 return; 129 } 130 if (e.Cancelled)//如果操作被取消 131 { 132 MessageBox.Show("操作被取消!"); 133 return; 134 } 135 136 if (MessageBox.Show(e.Result.ToString()) == MessageBoxResult.OK) 137 { 138 start.IsEnabled = true; 139 cancel.IsEnabled = false; 140 }; 141 } 142 143 private void DoSomething(object sender, DoWorkEventArgs e) 144 { 145 var state = new BarState();//自定义属性 146 for (int i = 0; i <= 100; i++) 147 { 148 Thread.Sleep(100); 149 state.Value = i; 150 _worker.ReportProgress(i, state);//报告进度 151 if (_worker.CancellationPending)//如果检查到取消操作,退出运行 152 { 153 e.Cancel = true;//通知RunWorkerCompletedEventArgs操作已取消 154 break; 155 } 156 }; 157 e.Result = "运行完成";//运行完成后传递参数给RunWorkerCompleted事件 158 } 159 160 private void Start(object sender, RoutedEventArgs e) 161 { 162 start.IsEnabled = false; 163 cancel.IsEnabled = true; 164 _worker.RunWorkerAsync();//运行 165 } 166 167 private void Stop(object sender, RoutedEventArgs e) 168 { 169 _worker.CancelAsync();//取消运行 170 start.IsEnabled = true; 171 cancel.IsEnabled = false; 172 } 173 } 174 }