多线程中的异步委托
在告别单线程,看看多线程能做什么中,为了在非UI线程中对界面中的控件t_AB赋值我们调用了控件的异步委托方法。尽管它可以很好地解决Windows窗体体系结构中的那个严格的规定,但是和单线程的赋值语句相比,使用异步委托的方式显得有些繁琐,况且它还仅仅是一个简单的TextBox控件。
代码对比:
tb_AB.Text = ab.ToString();
ab= int.Parse(tb_A.Text) + int.Parse(tb_B.Text);
ab= int.Parse(tb_A.Text) + int.Parse(tb_B.Text);
tb_AB.BeginInvoke(new add(addA_B), ab);
private delegate void add(int a);
private void addA_B(int result)
{
tb_AB.Text = result.ToString();
}
通过对比,是不是发现在单线程中一条语句就能说清楚的事情,到了多线程中却要绕个圈才能回到正题上。就好想一个人坐火车到了一个陌生的城市,在火车站拦了个的士要去汽车站,然后黑心的出租车师傅拉着你在火车站周围转了一个小时,等你下车后才发现,其实汽车站就在火车站马路对面拐个弯……
那么如果要是需要在非UI线程中给多个不同的控件赋予不同类型的值得话,是不是要想上篇说的那样一个一个赋值呢?答案当然是:NO。下面我们就这个问题的解决方法给出实例。
界面:
代码:
/// <summary>
/// 自定义事件
/// </summary>
public class MyProgressEvents : EventArgs
{
public string Msg;
public int PercentDone;
public MyProgressEvents(string msg, int per)
{
Msg = msg;
PercentDone = per;
}
}
private delegate void MyProgressEventsHandler(object sender, MyProgressEvents e);
赋值方法:
/// <summary>
/// 更新控件属性
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void UpdateUI(object sender, MyProgressEvents e)
{
lblStatus.Text = e.Msg;
myProgressControl.Value = e.PercentDone;
}
/// <summary>
/// 变化值
/// </summary>
private void RunsOnWorkerThread()
{
for (; i < 101; i++)
{
ShowProgress(Convert.ToString(i) + "%", i);
Thread.Sleep(1000); //控制时间间隔
}
}
public void ShowProgress(string msg, int percentDone)
{
// Wrap the parameters in some EventArgs-derived custom class:
System.EventArgs e = new MyProgressEvents(msg, percentDone);
object[] pList = { this, e };
BeginInvoke(new MyProgressEventsHandler(UpdateUI), pList);
}
/// <summary>
/// button2的点击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
Thread.CurrentThread.Name = "UIThread";
myThread = new Thread(new ThreadStart(RunsOnWorkerThread));
myThread.Name = "progress"; //当前线程的名称
myThread.Start();
}
通过运行程序可以看到,点击button2之后,按钮后面的lable和下方的进度条的值会以一秒的时间周期同步刷新。
需要说明,代码来自MSDN上的一篇文章,在此借花献佛了,不过同样可以说明问题。