C#应用 - 如何跨线程调用窗体控件
C# 应用过程中,经常调用各种控件实现程序员的各种目的。如果需要跨线程调用控件,那么可以看看这个案例!(基本控件只能在被创建的线程内使用,故跨线程,那么忽略跨线程,要么将传输给控件的值通过各种方法传输给该线程内使用)
工具/原料
visual studio 2015
跨线程操作无效
1、新建工程后。需要新建线程,在线程中调用控件,此处在线程中打印信息。按照需求,添加如下控件。
2、添加基本代码:“新建线程”:thread1 = new 哌囿亡噱Thread(Task_Thread);thread1.Start();开启线程。“关闭线程”:thread1.A芟鲠阻缒bort();“线程任务”: while (Thread.CurrentThread.ThreadState != ThreadState.Aborted) { RecordInfo("当前线程ID:" + Thread.CurrentThread.ManagedThreadId.ToString()+ "状态:"+ Thread.CurrentThread.IsAlive.ToString()); Thread.Sleep(1000); }
3、如图出现“线程间操作无效”报警
方案1:禁止编译器检查线程调用异常(不推荐)
1、在窗体初始化中添加Control.CheckForIllegalCrossThreadCalls = false;不检查线程间调用异常。同样无法检测其他线程调用异常,不推荐!
2、此处示例较为简单,结果显示正确。
方案2:delegate和invoke
1、全部代码如下,基本框架没变,只是在调用控件时做了处理
2、在调用函数中设置if (textBox1.InvokeRequired){// 当一个控件的Inv泠贾高框okeRequired属性值为真时,说明有一个创建它以外的线程想访问它Action<string> actionDelegate = (x) => { this.textBox1.AppendText(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss:fff \r\n") + x.ToString() + "\r\n"); };this.textBox1.Invoke(actionDelegate, info);}主线程外的其他线程要调用时,触发InvokeRequired,即可通过Invoke,完成设置的委托。
方案3:delegate和BeginInvoke
1、方案3相比方案2只是将invoke改为begininvoke。
2、Invoke 与begininvoke区别在于是否阻俅驺小钒塞调用线程。invoke:会阻塞当前线程,直到invoke调用结束(委托方刮茕栓双法执行结束),才继续执行(同步调用)。begininvoke:不会阻塞当前线程,只将调用方法封送完毕就返回,不会阻塞调用者线程(异步调用)。
使用BackgroundWorker组件
1、添加 BackgroundWorker 组件后,设置属性。
2、图实例:RunWorkerAsync() 开启辅助线程CancelAsync();关闭辅助线程钱砀渝测(属性中要允许关闭)芟鲠阻缒backgroundWorker1_DoWork()开启辅助线程后,进入DoWork中ReportProgress();在辅助线程中改变的量可通过此接口传输backgroundWorker1_RunWorkerCompleted();辅助线程结束时触发backgroundWorker1_ProgressChanged();改变ReportProgress时触发ProgressPercentage/UserState为ReportProgress()中改变的量
3、显示效果如图