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 }

 

posted @ 2021-10-26 11:45  只吃肉不喝酒  阅读(469)  评论(0编辑  收藏  举报