您的位置:首页 > 产品设计 > UI/UE

多线程更新UI的常用方法

2016-06-15 19:34 453 查看
开发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("数据处理完毕!");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: