1. 线程间操作无效: 从不是创建控件“textBox1”的线程访问它
//Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace T2
{
public partial class Form1 : Form
{
private uint cnt = 0;
public Form1()
{
InitializeComponent();
textBox1.Text = cnt.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
cnt++;
textBox1.Text = cnt.ToString();
}
private void Reset_Click(object sender, EventArgs e)
{
cnt = 0;
textBox1.Text = cnt.ToString();
}
public void CallToChildThread()
{
cnt += 10;
textBox1.Text = cnt.ToString();
}
private void F1_Click(object sender, EventArgs e)
{
ThreadStart childref = new ThreadStart(CallToChildThread);
Console.WriteLine("In Main: Creating the Child thread");
Thread childThread = new Thread(childref);
childThread.Start();
}
}
}
按下F1按键,弹出:
“System.InvalidOperationException”类型的未经处理的异常在 System.Windows.Forms.dll 中发生
其他信息: 线程间操作无效: 从不是创建控件“textBox1”的线程访问它。
2. 通过UI控件的Invoke/BeginInvoke方法更新
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace T2
{
public partial class Form1 : Form
{
private uint cnt = 0;
// 第一步:定义委托类型
// 将text更新的界面控件的委托类型
delegate void SetTextCallback(string text);
public Form1()
{
InitializeComponent();
textBox1.Text = cnt.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
cnt++;
textBox1.Text = cnt.ToString();
}
private void Reset_Click(object sender, EventArgs e)
{
cnt = 0;
textBox1.Text = cnt.ToString();
}
//第二步:定义线程的主体方法
private void CallToChildThread()
{
cnt += 10;
SetText(cnt.ToString());
}
//第三步:定义更新UI控件的方法
/// <summary>
/// 更新文本框内容的方法
/// </summary>
/// <param name="text"></param>
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired)//如果调用控件的线程和创建创建控件的线程不是同一个则为True
{
while (!this.textBox1.IsHandleCreated)
{
//解决窗体关闭时出现“访问已释放句柄“的异常
if (this.textBox1.Disposing || this.textBox1.IsDisposed)
return;
}
SetTextCallback d = new SetTextCallback(SetText);
this.textBox1.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = text;
}
}
private void F1_Click(object sender, EventArgs e)
{
ThreadStart childref = new ThreadStart(CallToChildThread);
Console.WriteLine("In Main: Creating the Child thread");
Thread childThread = new Thread(childref);
childThread.Start();
}
}
}