本帖最后由 吴步兵 于 2012-11-16 22:22 编辑
今天看了多线程的教学视频,碰到不允许跨线程调用Windows窗体的错误。教学视频里只是用TextBox.CheckForIllegalCrossThreadCalls = false;过滤掉检查。后来自己查看了MSDN,知道了跨线程调用控件的两种方法。
方法一、查询控件的 InvokeRequired 属性,如果 InvokeRequired 返回 true,则使用实际调用控件的委托来调用 Invoke,如果 InvokeRequired 返回 false,则直接调用控件。实例如下- delegate void SetTextCallback(string text);
- //---------------------使用 Invoke 实现的安全访问-----------------
- private void setTextSafeBtn_Click(object sender, EventArgs e)
- {
- Thread demoThread = new Thread(new ThreadStart(ThreadProcSafe));
- demoThread.Start();
- }
- private void ThreadProcSafe()
- {
- this.SetText("这是使用Invoke实现安全的调用方法.");
- }
- private void SetText(string text)
- {
- //检查控件的InvokeRequired是否为true,是则ThreadProcSafe方法会创建SetTextCallback的一个实例,并将该实例传递给窗体的Invoke方法。
- //这使得SetText方法被创建TextBox控件的线程调用,而且在此线程上下文中将直接设置Text属性
- if (this.textBox1.InvokeRequired)
- {
- SetTextCallback d = new SetTextCallback(SetText);
- this.Invoke(d, new object[] { text });
- }
- else//InvokeRequired为false则直接赋值
- {
- this.textBox1.Text = text;
- }
- }
复制代码 方法二:使用 BackgroundWorker 进行线程安全调用
在应用程序中实现多线程的首选方式是使用BackgroundWorker组件。BackgroundWorker 组件使用事件驱动模型实现多线程。后台线程运行 DoWork 事件处理程序,而创建控件的线程运行 ProgressChanged 和 RunWorkerCompleted 事件处理程序。可以从 ProgressChanged 和 RunWorkerCompleted 事件处理程序调用控件。实例如下:- //-------------------------使用 BackgroundWorker 实现的安全访问(还是不太明白)-----------------------------
- private void setTextBackgroundWorkerBtn_Click(object sender, EventArgs e)
- {
- this.backgroundWorker1.RunWorkerAsync();
- }
- private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
- {
- this.textBox1.Text = "使用 BackgroundWorker 实现的安全访问.";
- }
复制代码 但两种方法到底有什么区别和优缺点呢。还是搞不太懂啊。
|