跨线程调用Windows窗体控件[FreeDownload]
如对线程的操作不正确,在跨线程调用Windows窗体控件时会有产生InvalidOperationException异常。
该异常提示[线程间操作无效: 从不是创建控件“listBox1”的线程访问它.]。
我相信很多人通过设置Control.CheckForIllegalCrossThreadCalls属性为false禁止捕获对错误线程的调用。
这种强制性的禁止捕获不是人性化的选项。
我们可以通过控件的Invoke方法来实现跨线程调用Windows窗体控件。
下面的源代码演示线程操作:
代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace VJSDN.Tech.ThreadAccess
{
//跨线程调用的方法委托原型。
public delegate void ShowMessageMethod(string msg);
//跨线程调用的方法委托原型。
public delegate void CreateControlMethod();
//注:A线程:主线程. 主线程是指当前窗体所在的线程.
// B线程:用户创建的线程。
// C线程:带参数的线程。
public partial class Form1 : Form
{
private Thread _threadB = null; //第2个线程.创建控件。
private Thread _threadC = null; //第3个线程.带参数的线程。
private Button _btnOnB = null; //由第2个线程创建的按钮控件。
private ListBox _listBoxOnB = null;//由第2个线程创建的ListBox控件。
private Panel _PanelOnB = null;//由第2个线程创建的Panel控件。
public Form1()
{
InitializeComponent();
//是否捕获对错误线程的调用,这些调用访问控件的 System.Windows.Forms.Control.Handle 属性。
//Control.CheckForIllegalCrossThreadCalls = false;
}
private void btnCreateThreadB_Click(object sender, EventArgs e)
{
//在主线程内创建线程B.
_threadB = new Thread(new ThreadStart(MethodThreadB)); //启动线程。
_threadB.Start();
}
private void createC_Click(object sender, EventArgs e)
{
//在主线程内创建带参数的线程C.
_threadC = new Thread(new ParameterizedThreadStart(MethodThreadC));
_threadC.Start(100); //往线程C传送参数100,计算100以内的数字加总。
}
//C线程正在运行....
private void MethodThreadC(object param)
{
int total = int.Parse(param.ToString());
this.Invoke(new ShowMessageMethod(this.ShowMessage), "线程C正在计数:1+2+n=?(n<=" + param.ToString() + ")");
int result = 0; //计数器
for (int i = 1; i <= total; i++) result += i;
this.Invoke(new ShowMessageMethod(this.ShowMessage), "线程C计算结果:" + result.ToString());
}
//B线程正在运行....
private void MethodThreadB()
{
//跨线程操作:试图在B线程内给A线程的panel2控件插入子控件.
this.Invoke(new CreateControlMethod(this.CreatePanelOnThreadB)); //创建Panel
this.Invoke(new CreateControlMethod(this.CreateButtonOnThreadB)); //创建按钮
this.Invoke(new CreateControlMethod(this.CreateListBoxOnThreadB)); //创建ListBox
this.Invoke(new ShowMessageMethod(this.ShowMessage), "线程B操作线程A内的ListBox控件");
this.Invoke(new ShowMessageMethod(this.ShowMessage), "如能显示消息,表示操作成功!");
}
//注意:这个方法与CreateControlMethod委托原型相同。
private void CreateControlCross(Label lbl)
{
_PanelOnB.Controls.Add(lbl);
}
//注意:这个方法与ShowMessageMethod委托原型相同。
private void ShowMessage(string msg)
{
this.listBox1.Items.Add(msg);
}
private void CreatePanelOnThreadB()
{
_PanelOnB = new Panel();
_PanelOnB.BackColor = System.Drawing.Color.Silver;
_PanelOnB.Location = new System.Drawing.Point(264, 12);
_PanelOnB.Name = "panel2";
_PanelOnB.Size = new System.Drawing.Size(244, 355);
_PanelOnB.TabIndex = 1;
this.Controls.Add(_PanelOnB); //创建Panel容器
Label _lblB = new Label();
_lblB.AutoSize = true;
_lblB.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
_lblB.Location = new System.Drawing.Point(3, 7);
_lblB.Name = "label1";
_lblB.Size = new System.Drawing.Size(84, 12);
_lblB.TabIndex = 0;
_lblB.Text = "线程B,用户创建的线程";
_PanelOnB.Controls.Add(_lblB); //Panel容器内加入一个label
}
private void CreateButtonOnThreadB()
{
_btnOnB = new Button();
_btnOnB.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
_btnOnB.Location = new System.Drawing.Point(5, 63);
_btnOnB.Name = "btnSendToA";
_btnOnB.Size = new System.Drawing.Size(167, 23);
_btnOnB.TabIndex = 4;
_btnOnB.Text = "给线程A创建的控件发消息";
_btnOnB.UseVisualStyleBackColor = true;
_btnOnB.Click += new System.EventHandler(this.btnSendToA_Click);
//panel2是主线程上创建的控件。
_PanelOnB.Controls.Add(_btnOnB);
}
private void CreateListBoxOnThreadB()
{
_listBoxOnB = new ListBox();
_listBoxOnB.FormattingEnabled = true;
_listBoxOnB.ItemHeight = 12;
_listBoxOnB.Location = new System.Drawing.Point(5, 240);
_listBoxOnB.Name = "listBox2";
_listBoxOnB.Size = new System.Drawing.Size(236, 112);
_listBoxOnB.TabIndex = 2;
//panel2是主线程上创建的控件。
_PanelOnB.Controls.Add(_listBoxOnB);
}
private void btnSendToA_Click(object sender, EventArgs e)
{
listBox1.Items.Add("线程B发消息给A");
}
private void btnSendToB_Click(object sender, EventArgs e)
{
if (_listBoxOnB != null)
_listBoxOnB.Items.Add("线程A发消息给B");
else
MessageBox.Show("线程B还没创建呢!");
}
}
}
转帖自[易学网]