winform 使用了invoke还是报错 线程间操作无效: 从不是创建控件“Form2”的线程访问它。”
winform开发中,遇到“线程间操作无效: 从不是创建控件“Form2”的线程访问它”,明明使用了网上说的this.invoke,怎么还是会报这个错误呢?
代码如下,由于是测试configureAwait功能时发现的,所以带了它的一些使用
private async void button7_Click(object sender, EventArgs e)//点击第一个按钮 { int i = 1; if (i == 1) { await longTask().ConfigureAwait(false);//这里调用长任务处理,使用ConfigureAwait为false,表示不用回到UI线程 } else { wt("i不等于1"); } wt("UI线程"); } public async Task longTask() { wt("开始task"); //一些耗时任务 await Task.Run(async () => { Form2.Instance.ShowDialog();//弹出 Form2窗体 await Task.Delay(5000); wt("窗口关闭"); }).ConfigureAwait(false); await Task.Delay(2000); wt("调用窗口任务完成"); } public async Task closeForm2()//点击第二个按钮 { wt("closeForm2"); await Task.Delay(2000).ConfigureAwait(false); //等待2s后执行下面语句 this.Invoke(new Action(() =>//跨线程调用 { wt("closeForm2_invoke"); Form2.Instance.Close();//关闭Form2,但会在这里报错 })); wt("closeForm结束"); }
public void wt(string msg)
{
Console.WriteLine($"{msg}:{Thread.CurrentThread.ManagedThreadId}");
}
上述代码中,红色表明的地方会报错:线程间操作无效: 从不是创建控件“Form2”的线程访问它。
明明使用了委托了,怎么还会报此错误呢,后研究发现问题出在this.invoke上。
Invoke方法会顺着控件树向上搜索直到找到创建控件的那个线程(通常是主线程),然后进入那个线程改变控件的外观,确保不发生线程冲突。
this指向错了,这里的this指Form1,我们要关闭的是Form2,所以改指就ok了,应改为:
Form2.Instance.Invoke(new Action(() => { wt("closeForm2_invoke"); Form2.Instance.Close(); }));
运行的结果