多线程更新UI的常用方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程更新UI的常用方法相关的知识,希望对你有一定的参考价值。
开发Winform或者WPF相关GUI程序中,遇到执行耗时程序片段,并且需要在ui界面上实时展示状态信息的问题时,为了防止界面出现假死状态,会用到多线程技术,异步跨线程访问ui界面元素;下面总结下Winform和WPF中常用的几种异步跨线程访问ui界面的技术。
Winform中常用技术
1、采用BackgroundWorker控件
public partial class Form1 : Form { private BackgroundWorker worker; public Form1() { InitializeComponent(); worker = new BackgroundWorker(); worker.WorkerReportsProgress = true;// To report progress from the background worker we need to set this property worker.DoWork += worker_DoWork;// This event will be raised on the worker thread when the worker starts worker.ProgressChanged += worker_ProgressChanged;// This event will be raised when we call ReportProgress } private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) { progressBar1.Value = e.ProgressPercentage; lblPercent.Text = string.Format("{0}%", e.ProgressPercentage); if (e.ProgressPercentage == 100) { MessageBox.Show("数据处理完毕!"); } } private void worker_DoWork(object sender, DoWorkEventArgs e) { for (int i = 1; i <= 100; i++) { // Report progress to ‘UI‘ thread worker.ReportProgress(i); Thread.Sleep(100); } } private void btnCompute_Click(object sender, EventArgs e) { //Start the background worker worker.RunWorkerAsync(); } }
2、采用Timer控件
public partial class Form1 : Form { private Timer timer; private int current; public Form1() { InitializeComponent(); timer = new Timer(); timer.Interval = 500; timer.Tick += timer_Tick; } private void timer_Tick(object sender, EventArgs e) { progressBar1.Value = current; lblPercent.Text = string.Format("{0}%", current); if (current == 100) { timer.Stop(); MessageBox.Show("数据处理完毕!"); } } private void btnCompute_Click(object sender, EventArgs e) { Thread thread = new Thread(new ThreadStart(doWork)); thread.Start(); timer.Start(); } private void doWork() { for (int i = 1; i <= 100; i++) { current = i; Thread.Sleep(100); } } }
3、采用委托的方式
public partial class Form1 : Form { private delegate void UpdateProgress(int percent); public Form1() { InitializeComponent(); } private void btnCompute_Click(object sender, EventArgs e) { Thread thread = new Thread(new ThreadStart(doWork)); thread.Start(); } private void doWork() { for (int i = 1; i <= 100; i++) { //progressBar1.BeginInvoke((Action)(() => { progressBar1.Value = i; })); //lblPercent.BeginInvoke((Action)(() => { lblPercent.Text = string.Format("{0}%", i); })); //if (i == 100) //{ // MessageBox.Show("数据处理完毕!"); //} update(i); Thread.Sleep(100); } } private void update(int percent) { if (InvokeRequired) { this.Invoke(new UpdateProgress(update), percent); } else { progressBar1.Value = percent; lblPercent.Text = string.Format("{0}%", percent); if (percent == 100) { MessageBox.Show("数据处理完毕!"); } } } }
WPF中常用技术
WPF中引入了Dispatcher,常用来解决非ui线程中更新ui控件状态的问题。
/// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { private delegate void UpdateProgress(int percent); public MainWindow() { InitializeComponent(); } private void BtnCompute_OnClick(object sender, RoutedEventArgs e) { Task task = new Task(DoWork); task.Start(); } private void DoWork() { for (int i = 1; i <= 100; i++) { //Dispatcher.BeginInvoke((Action)(() => //{ // progressBar1.Value = i; // lblPercent.Content = string.Format("{0}%", i); // if (i == 100) // { // MessageBox.Show("数据处理完毕!"); // } //})); Dispatcher.BeginInvoke(new UpdateProgress(Update), i); Thread.Sleep(100); } } private void Update(int percent) { progressBar1.Value = percent; lblPercent.Content = string.Format("{0}%", percent); if (percent == 100) { MessageBox.Show("数据处理完毕!"); } } }
以上是关于多线程更新UI的常用方法的主要内容,如果未能解决你的问题,请参考以下文章