在开发winform时经常会用到多线程防止界面出现假死现象,比如当你单击某个按钮时,需要执行很多代码,但是在执行过程中想实时的将当前执行的情况报告给用户,类型进度条或文本什么的。

 这个时候很显然,如果你把要实现的内容放在按钮方法里时,其实界面要等这个按钮执行完后才能输出来,这个时候就达不到我们的预期了;那么怎么才能解决问题呢。

 我初略终结了一下有以下几种方法:

     .采用BackgroundWorker控件,这个控件将要实时输出的内容写在事件中;

   private void button1_Click(object sender, EventArgs e)
{
//异步执行逻辑
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//实现业务逻辑
int i = ;
i = Math.Abs(i);
//报告当前处理进度
backgroundWorker1.ReportProgress();
} private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//当前进度
int cuur = e.ProgressPercentage;
//实现跨线程控件的输出
this.label1.Text = cuur.ToString();
} private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//执行完毕可以报告信息
this.label1.Text = "ok";
} .采用委托的方式实现灵活引用Invoke; private void button2_Click(object sender, EventArgs e)
{
//异步执行逻辑
Thread thread = new Thread(ThreadFunc);
thread.IsBackground = true;
thread.Start();
}
private void ThreadFunc()
{
//实现业务逻辑
int i = ;
i = Math.Abs(i);
//报告当前处理进度
SetLabel(i.ToString());
}
//定义委托
delegate void SetLabelHandler(string text);
//实现方法
private void SetLabel(string text)
{
if (InvokeRequired)
{
Invoke(new SetLabelHandler(SetLabel), text);
}
else
{
this.label1.Text = text;
}
}   .采用Lamada表达式动态实现委托调用。 private void button3_Click(object sender, EventArgs e)
{
//异步执行逻辑
Thread thread = new Thread(Func);
thread.IsBackground = true;
thread.Start();
}
private void Func()
{
//实现业务逻辑
int i = ;
i = Math.Abs(i);
//报告当前处理进度
AsyncUI(() => { label1.Text = i.ToString(); });
}
public void AsyncUI(Action action)
{
if (InvokeRequired)
{
Invoke(action);
}
else
{
action();
}
} 以上是我总结的三种,至于有没有其他方法,欢迎大家来拍砖,在这里我想推荐的是第三种方法,这个方法最灵活。 下面来谈谈我对这三种的看法: 对应第一种方法:使用简单,拖控件就ok,但是对应需要显示更负责的数据时比较麻烦; 对应第二种方法:可以不用拖控件来自由定制,但是同第一种方法一样,如果需要显示更多控件数据,也要定义很多方法和委托,太冗余累赘; 对于第三种方法:我个人非常喜欢,代码在需要的时候动态使用,但是我也没有仔细分析该方法的性能问题。
04-21 04:34
查看更多