A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 吴步兵 中级黑马   /  2012-11-9 17:54  /  1257 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 吴步兵 于 2012-11-16 22:22 编辑

今天看了多线程的教学视频,碰到不允许跨线程调用Windows窗体的错误。教学视频里只是用TextBox.CheckForIllegalCrossThreadCalls = false;过滤掉检查。后来自己查看了MSDN,知道了跨线程调用控件的两种方法。
方法一、查询控件的 InvokeRequired 属性,如果 InvokeRequired 返回 true,则使用实际调用控件的委托来调用 Invoke,如果 InvokeRequired 返回 false,则直接调用控件。实例如下
  1. delegate void SetTextCallback(string text);
  2. //---------------------使用 Invoke 实现的安全访问-----------------
  3. private void setTextSafeBtn_Click(object sender, EventArgs e)
  4. {
  5. Thread demoThread = new Thread(new ThreadStart(ThreadProcSafe));

  6. demoThread.Start();

  7. }
  8. private void ThreadProcSafe()
  9. {
  10. this.SetText("这是使用Invoke实现安全的调用方法.");
  11. }
  12. private void SetText(string text)
  13. {
  14. //检查控件的InvokeRequired是否为true,是则ThreadProcSafe方法会创建SetTextCallback的一个实例,并将该实例传递给窗体的Invoke方法。
  15. //这使得SetText方法被创建TextBox控件的线程调用,而且在此线程上下文中将直接设置Text属性
  16. if (this.textBox1.InvokeRequired)
  17. {
  18. SetTextCallback d = new SetTextCallback(SetText);
  19. this.Invoke(d, new object[] { text });
  20. }
  21. else//InvokeRequired为false则直接赋值
  22. {
  23. this.textBox1.Text = text;
  24. }
  25. }
复制代码
方法二:使用 BackgroundWorker 进行线程安全调用
在应用程序中实现多线程的首选方式是使用BackgroundWorker组件。BackgroundWorker 组件使用事件驱动模型实现多线程。后台线程运行 DoWork 事件处理程序,而创建控件的线程运行 ProgressChanged 和 RunWorkerCompleted 事件处理程序。可以从 ProgressChanged 和 RunWorkerCompleted 事件处理程序调用控件。实例如下:
  1. //-------------------------使用 BackgroundWorker 实现的安全访问(还是不太明白)-----------------------------
  2. private void setTextBackgroundWorkerBtn_Click(object sender, EventArgs e)
  3. {
  4. this.backgroundWorker1.RunWorkerAsync();
  5. }
  6. private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  7. {
  8. this.textBox1.Text = "使用 BackgroundWorker 实现的安全访问.";
  9. }
复制代码
但两种方法到底有什么区别和优缺点呢。还是搞不太懂啊。

评分

参与人数 1技术分 +1 收起 理由
张文 + 1

查看全部评分

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马