例如要在另一个线程里执行Test方法,改变form的标题
private void Form1_Load(object sender, EventArgs e)
{
Thread t = new Thread(Test);
t.Start();
}
public void Test(){
this.Text="aaa";
}
winform下跨线程操作Control主要有两种方式,
1,偷懒的方式
直接把Control的检查合法跨线程的设置为false,不检查
Control.CheckForIllegalCrossThreadCalls = false;
但是,在面对一些封装好的Control,例如,视频播放的AForge(2.25版本)时,发现就算设置了
VideoSourcePlayer.CheckForIllegalCrossThreadCalls = false
也没用,而且vs2019居然不报错(太坑了)
目测是没有通过这个字段来检测是否合法跨线程
后来我写了try catch才发现的错误
“Cross thread access to the control is not allowed.”
问题出在AForge.Controls.VideoSourcePlayer.CheckForCrossThreadAccess()
看了源码
private void CheckForCrossThreadAccess()
{
if (!base.IsHandleCreated)
{
CreateControl();
if (!base.IsHandleCreated)
{
CreateHandle();
}
}
if (base.InvokeRequired)
{
throw new InvalidOperationException("Cross thread access to the control is not allowed.");
}
}
问题出在IsHandleCreated,和InvokeRequired
这两个都是只读的,分别是判断是否时form所在线程创造的,是否需要委托,
然后,只能使用委托的方式实现跨线程操作Control了,’
就有了另一个坑
委托的实现方式
Action的方式
public void Test(){
new Action(Testt).BeginInvoke(null, null);
}
public void Testt(){
this.Text="aa";
}
试了下,一样会报跨线程异常的问题
后来才发现,必须要使用Form的BeginInvoke,并且显示定义delegate才能起作用
public delegate void MyInvoke();
public void Test(){
MyInvoke mi = new MyInvoke(Testt);
this.BeginInvoke(mi); //这里是关键
}
个人猜测是this.BeginInvoke同时也把this对象传递给了跨线程要执行的内容