关于多线程的问题,一直没有弄太懂, 今天在 CodeProject 上看到一个很好的讲解多线程例子, 为增强理解,用我自己理解的方式记录下来,以便遗忘后查看。
如下图所示, 点击启动进度条后, 进度条会开始变化。
代码如下:
1 private void btnStartProg_Click(object sender, RoutedEventArgs e)
2 {
3 startN = Convert.ToInt32(startNum.Text);
4 endN = Convert.ToInt32(endNum.Text);
5
6 progBar.Minimum = startN;
7 progBar.Maximum = endN;
8
9 for (int progValue = startN; progValue < endN; progValue++)
10 {
11 progBar.Value = progValue;
12 }
13 }
当 End 数值大于10e6 时, 会出线界面无响应状态,如下图所示:
之所以有这种情况是因为单线程条件下, 当数值过大时候, 线程阻塞在 for 循环位置, 来不及更新界面。
要解决这个问题很简单, 在 UI 线程外增加一个新的线程(wpf中采用dispatcher.invoke, 若不是在UI线程中, 可采用事件的形式),使得进度条的变化在另一线程中进行。
1 private void btnStartProg_Click(object sender, RoutedEventArgs e)
2 {
3 startN = Convert.ToInt32(startNum.Text);
4 endN = Convert.ToInt32(endNum.Text);
5
6 progBar.Minimum = startN;
7 progBar.Maximum = endN;
8
9 System.Threading.Thread changeValueThread = new System.Threading.Thread(ChangeProgessValue);
10 changeValueThread.Start();
12 }
13
14 private void ChangeProgessValue()
15 {
16 for (int progValue = startN; progValue < endN; progValue++)
17 {
18 Dispatcher.Invoke(() => progBar.Value = progValue);
19 }
20 }
另一种处理多线程的通信方式可基于事件机制进行通信, 具体如下图所示(参考 https://www.jianshu.com/p/8faae685a468):
在 wpf 中, 当界面的某个值大量的变化的时候,采用绑定属性(全局变量)的方式,免去根据 Name 来查找控件位置, 速度会快很多。
具体代码如下:
1 // 类继承 INotifyPropertyChanged, 实现并重载事件处理方法
2 public event PropertyChangedEventHandler PropertyChanged;
3 protected virtual void OnpropertyChanged(string propertyName)
4 {
5 if(this.PropertyChanged != null)
6 {
7 this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName))
8 }
9 }
10 // 定义一个属性
11 private int currentValue;
12 public int CurrentValue
13 {
14 get {return currentValue}
15 set
16 {
17 currentValue = value;
18 OnpropertyChanged("CurrentValue");
19 }
20 }
21
22 // 然后在 .xmal 需要改变的值得位置添加值绑定 Value = "{Binding CurrentValue}"