1、不安全的方法: 将 Control.CheckForIllegalCrossThreadCalls 设置为false (.net1.0中没有)

2、安全的方法: 异步委托(不要将除了控件访问外其他逻辑代码放到委托的回调方法中)

private void button1_Click(object sender, System.EventArgs e)
{
    //实例化一个线程,并引用线程开始执行时要调用的方法
    //这个方法在线程调用start()方法时启动
    barProgress = new Thread(new ThreadStart(ProgressProc)); //调用线程启动ProgressProc方法
    barProgress.IsBackground = true;
    barProgress.Start();
}
private void ProgressProc()
{
    MethodInvoker mi = new MethodInvoker(UpdateProgress);//MethodInvoker表示一个委托,该委托可以执行托管代码中声明为
    while (true)
    {
        Invoke(mi);
        int sleepTime = this.waitTime;
        Thread.Sleep(sleepTime);
    }
}
private void UpdateProgress()  //实现UpdateProgress
{
    //更新界面
}

3、安全的方法: 就是使用BackgroundWorker来替代你自己创建的线程(.net1.0中没有)

BackgroundWorker是一个在System.ComponentModel命名空间下帮助类,它管理着工作线程。它提供了以下特性:

  • "cancel" 标记,对于给工作线程打信号让它结束而没有使用 Abort的情况
  • 提供报道进度,完成度和退出的标准方案
  • 实现了IComponent接口,允许它参与Visual Studio设计器
  • 在工作线程之上做异常处理
  • 更新Windows Forms控件以应答工作进度或完成度的能力

最后两个特性是相当地有用:意味着你不再需要将try/catch语句块放到你的工作线程中了,并且更新Windows Forms控件不需要调用 Control.Invoke了。

BackgroundWorker使用线程池工作,对于每个新任务,它循环使用避免线程们得到休息。这意味着你不能在 BackgroundWorker线程上调用 Abort了。

下面是使用BackgroundWorker最少的步骤:

  • 实例化 BackgroundWorker,为DoWork事件增加委托。
  • 调用RunWorkerAsync方法,使用一个随便的object参数。

这就设置好了它,任何被传入RunWorkerAsync的参数将通过事件参数的Argument属性,传到DoWork事件委托的方法中,下面是例子:

class Program {
  static BackgroundWorker bw = new BackgroundWorker();
  static void Main() {
    bw.DoWork += bw_DoWork;
    bw.RunWorkerAsync ("Message to worker");     
    Console.ReadLine();
  } 
  static void bw_DoWork (object sender, DoWorkEventArgs e)  {
    // 这被工作线程调用
    Console.WriteLine (e.Argument);        // 写"Message to worker"
    // 执行耗时的任务...
  }

BackgroundWorker也提供了RunWorkerCompleted事件,它在DoWork事件完成后触发,处理RunWorkerCompleted事件并不是强制的,但是为了查询到DoWork中的异常,你通常会这么做的。RunWorkerCompleted中的代码可以更新Windows Forms 控件,而不用显示的信号编组,而DoWork中就可以这么做。

添加进程报告支持:

  • 设置WorkerReportsProgress属性为true
  • 在DoWork中使用“完成百分比”周期地调用ReportProgress方法,以及可选用户状态对象
  • 处理ProgressChanged事件,查询它的事件参数的 ProgressPercentage属性

ProgressChanged中的代码就像RunWorkerCompleted一样可以自由地与UI控件进行交互,这在更性进度栏尤为有用。

添加退出报告支持:

  • 设置WorkerSupportsCancellation属性为true
  • 在DoWork中周期地检查CancellationPending属性:如果为true,就设置事件参数的Cancel属性为true,然后返回。(工作线程可能会设置Cancel为true,并且不通过CancellationPending进行提示——如果判定工作太过困难并且它不能继续运行)
  • 调用CancelAsync来请求退出

下面的例子实现了上面描述的特性:

Code
using System;
using System.Threading;
using System.ComponentModel; 
class Program {
  static BackgroundWorker bw;
  static void Main()   {
    bw = new BackgroundWorker();
    bw.WorkerReportsProgress = true;
    bw.WorkerSupportsCancellation = true;

bw.DoWork += bw_DoWork;
    bw.ProgressChanged += bw_ProgressChanged;
    bw.RunWorkerCompleted += bw_RunWorkerCompleted; 
    bw.RunWorkerAsync ("Hello to worker");    
    Console.WriteLine ("Press Enter in the next 5 seconds to cancel");
    Console.ReadLine();
    if (bw.IsBusy) bw.CancelAsync();
    Console.ReadLine();
  } 
  static void bw_DoWork (object sender, DoWorkEventArgs e)   {
    for (int i = 0; i <= 100; i += 20) {
      if (bw.CancellationPending) {
        e.Cancel = true;
        return;
      }
      bw.ReportProgress (i);
      Thread.Sleep (1000);
    }
    e.Result = 123;    // 传递给 RunWorkerCopmleted
  } 
  static void bw_RunWorkerCompleted (object sender,RunWorkerCompletedEventArgs e)   {
    if (e.Cancelled)
      Console.WriteLine ("You cancelled!");
    else if (e.Error != null)
      Console.WriteLine ("Worker exception: " + e.Error.ToString());
    else
      Console.WriteLine ("Complete - " + e.Result);      // 从 DoWork
  } 
  static void bw_ProgressChanged (object sender,  ProgressChangedEventArgs e)   {
    Console.WriteLine ("Reached " + e.ProgressPercentage + "%");
  }
}

转载于:https://www.cnblogs.com/ladymeng/archive/2008/12/17/1356864.html

三种跨线程控件访问方法相关推荐

  1. C#.NET跨线程控件的相关操作

    在.NET中,如果我们在非UI线程上访问窗体上的控件的时候,会产生一个跨线程调用的异常,那么如何处理这种情况呢?在上一章中,我介绍了使用Control.Invoke方法,如果你不习惯使用委托,那么.N ...

  2. 关于跨线程操作GUI线程控件的疑问

    单元测试能够帮助开发人员确保所开发的模块.类以及类中的方法等的正确性,在项目开发过程中,及时进行单元测试能够避免不必要的BUG以及提高测试效率. 在本文中,我们会分别来学习如何使用MSTest.xUn ...

  3. Spring Boot 中三种跨域场景总结

    文章目录 1.什么是跨域 2.解决方案 2.1 存在的问题 3.SpringSecurity 3.1 方式一 3.2 方式二 4.OAuth2 5.小结 跨域这个问题松哥之前写过文章,但是最近收到小伙 ...

  4. 收藏夹导出至html,分享win7电脑中三种导出浏览器收藏夹地址方法

    使用win7电脑浏览器访问网站时为了更方便之后的访问用户都会讲有需要的网站收藏,但是有些用户在使用浏览器时并不习惯登陆账户就会导致收藏夹无法同步,之后电脑出现故障时或是浏览器出现问题收藏内容就会消失, ...

  5. 多角度对比数据中心常见的三种走线方式

    01 三种走线方式的施工图片 ▽下走线(地板下走线) ▽天花吊顶上走线 ▽机柜顶部走线 02 三种走线方式对比 通过上面的比较,毫无疑问,机柜顶部走线模式是最有优势的,给用户带来很多好处,包括维护方便 ...

  6. SAP-ABAP三种定义嵌套型结构的方法

    *第一种定义嵌套型结构的方法 DATA: BEGIN OF str1, f_name(4) TYPE c VALUE 'Brad', l_name(4) TYPE c VALUE 'Pitt', EN ...

  7. java 三种将list转换为map的方法详解

    这篇文章主要介绍了java 三种将list转换为map的方法详解的相关资料,需要的朋友可以参考下 java 三种将list转换为map的方法详解 在本文中,介绍三种将list转换为map的方法: 1) ...

  8. VS2008(C#)子页嵌套母版页的控件访问方法(二)

    VS2008(C#)子页嵌套母版页的控件访问方法(二)--嵌套两层母板页 子页嵌套了两层母版页后,访问第一层.第二层母版页中控件的方法如下 第一层母版页HTML代码 <%@ Master Lan ...

  9. mysql重复上一行的快捷_MySql三种避免重复插入数据的方法

    前言 MySql 在存在主键冲突或唯一键冲突的情况下,根据插入方式,一般有以下三种插入方式避免错误. insert ignore. replace into insert on duplicate k ...

最新文章

  1. C/C++面试题:什么是COM和ActiveX,简述DCOM。
  2. 笔记:《突破现实的困境:趋势、禀赋与企业家的大战略》
  3. 学术诚信的重要性_关于学术诚信
  4. 中label换行问题_如何巧妙处理 Git 多平台换行符问题(LF or CRLF)
  5. Android中AMS工作原理,Android AMS启动详解
  6. mysql 变量定义和赋值_MySQL变量解析
  7. CSS3 Gradient渐变
  8. 阶段3 2.Spring_04.Spring的常用注解_4 由Component衍生的注解
  9. 同步与互斥的基本原理
  10. 基于PC-DIMS脱机软件 的海克斯康三坐标机脱机编程软件手册。
  11. 【ES6-阮一峰博客阅读笔记】
  12. ip地址和域名的关系是什么?
  13. 干货 | 在搜索引擎广告关键词生成上,算法可以做什么?
  14. html表格添加序号,通过layui给数据表格添加序号
  15. 好用的提高生产力的Firefox插件LeechBlock
  16. 第2章 感知机 - 对偶形式
  17. java操作txt文本(一):遇到指定字符换行
  18. 用计算机算cos1,cos1等于多少怎么算
  19. win32汇编 屏幕截图保存BMP 学习笔记第三篇之odbg调试
  20. 获取当前时间时间戳的几种方式

热门文章

  1. LeetCode(389)——找不同(JavaScript)
  2. 【Vue】—数组对象变更检测
  3. 数据库原理—DBS的物理组成和结构模式(五)
  4. java小程序详解_微信小程序登录Java后台接口(详解,附示例代码)
  5. 基金一般拿多长时间合适?
  6. 远嫁的女人有没有偷偷哭过?有何经历?
  7. 2021年基金什么时候布局?
  8. 微信号承载私域流量的9条心得
  9. 实体与电商,有啥区别?
  10. 职场的秘密,你知道多少?