当支线程调用winfrom中的控件:
第一种办法:禁止编译器对跨线程访问做检查:
public Form1()
{
InitializeComponent();
// 加入这行
Control.CheckForIllegalCrossThreadCalls = false;
}
第二种办法: 使用delegate和invoke或者beginInvoke来从其他线程中调用控件
首先建一个winfrom页面如图:
Invoke用法程序:
/// <summary>
/// 支线线程调用Invoke
/// 输出--begin--
/// --end--
/// Before!Invoke!Main
///总结:Invoke的委托在主线程中执行
///Invoke在支线程中调用也会阻塞主线程。(当点击button1后,我试图去点击button2,却发现程序被阻塞了)
///Invoke还会阻塞支线程。(因为输出结果中没有出现After)
/// </summary>
private void ThreadInvoke()
{
listBox1.Items.Add("--begin--");
new Thread(() =>
{
Thread.CurrentThread.Name = "ThreadInvoke";
string temp = "Before!";
listBox1.Invoke(new Action(() =>
{
Thread.Sleep(10000);
this.listBox1.Items.Add(temp += "Invoke!" + Thread.CurrentThread.Name);
}));
temp += "After!";
}).Start();
listBox1.Items.Add("--end--");
}
private void button1_Click(object sender, EventArgs e)
{
Thread.CurrentThread.Name = "Main";
ThreadInvoke();
}
private void button2_Click(object sender, EventArgs e)
{
listBox1.Items.Add("button2_Click");
}
BeginInvoke用法程序:
/// <summary>
/// 支线程调用BeginInvoke
/// 输出--begin--
/// --end--
/// Before!After!Invoke!Main
/// 总结:BeginInvoke在主线程中执行。
/// BeginInvoke在支线程中调用也会阻塞主线程。
/// BeginInvoke相对于支线程是异步的。
/// </summary>
private void ThreadBeginInvoke()
{
listBox1.Items.Add("--begin--");
new Thread(() =>
{
Thread.CurrentThread.Name = "ThreadBeginInvoke";
string temp = "Before!";
listBox1.BeginInvoke(new Action(() =>
{
Thread.Sleep(10000);
this.listBox1.Items.Add(temp += "Invoke!" + Thread.CurrentThread.Name);
}));
temp += "After!";
}).Start();
listBox1.Items.Add("--end--");
}
private void button1_Click(object sender, EventArgs e)
{
Thread.CurrentThread.Name = "Main";
ThreadBeginInvoke();
}
private void button2_Click(object sender, EventArgs e)
{
listBox1.Items.Add("button2_Click");
}