目录
2.1 可视化控件的 Invoke 和 BeginInvoke 方法
如下由于可视化控件是由 “UI 线程” 创建的,而数据处理任务通常由其他一些线程执行,可将这些线程称为 “工作线程”,因此在用户界面上显示工作线程执行状态信息本质上是一个 “跨线程访问可视化控件” 的问题。
1 细说 UI 线程
在 Windows 应用程序中,窗体是由 “UI 线程” 创建的。窗体和控件之所以能响应用户操作,关键在于负责创建它们的 UI 线程拥有一个 “消息循环”。Windows 消息循环在代码中就是一个循环结构(比如 while 循环),它不停地从操作系统中获取 Windows 消息,然后交给程序处理。
注:包含 Windows 消息循环的线程称为 “UI线程”,一般 UI 线程结束意味着程序退出。另外,操作系统为每个 UI 线程维护一个消息队列,一个 UI 线程对应有一个消息队列,UI 线程负责处理对应消息队列中的消息。
由于 UI 线程负责创建和绘制窗体和控件,因此 Windows 不允许其它线程直接访问可视化控件。其原因是 Windows 无法控制其它线程将如何使用这些控件,而对控件某些属性的设置和方法调用有可能会直接影响到控件的外观。
因此,Windows 规定:
不能跨线程直接访问窗体和控件,对它们的访问必须转由 UI 线程来负责处理。
2 跨线程访问可视化控件的基本方法
2.1 可视化控件的 Invoke 和 BeginInvoke 方法
在 .NET Framework 中,所有可视化的控件都是从 System.Windows.Forms.Control 类派生出来的,考虑到跨线程访问控件的需要,Control 类提供了相应的方法完成跨线程更新界面工作。
public object Invoke(Delegate method);
public object Invoke(Delegate method, params object[] args);
private void __PlayThread(object info)
{
this.Invoke((Action)delegate()
{
textBox1.Text = "Hello World!";
});
// 1. 传送参数
Action<string> del = delegate(string InputValue)
{
textBox1.Text = InputValue;
};
this.Invoke(del, info);
// 2.
Action<string> del = (string InputValue) =>
{
textBox1.Text = InputValue;
};
this.Invoke(del, info);
// 3.
this.Invoke((Action<string>)delegate(string InputValue)
{
textBox1.Text = InputValue;
}, info);
}