如何:从线程中操作控件

BackgroundWorker 组件替换了 BeginInvoke 方法并添加了功能;但是也可选择保留 BeginInvoke 方法以备向后兼容和将来使用。 有关更多信息,请参见 BackgroundWorker 组件概述

多线程处理最适合于运行类模块的处理器密集型过程。 与其他组件不同的是,从单独的线程直接调用控件中的方法会存在一些问题。 影响控件的方法只应该在创建控件的线程上执行。 由于从一个线程封送调用并跨线程边界将其发送到另一个线程会耗费大量的系统资源,所以应避免重复调用其他线程上的控件。 在最佳情况下,从其他线程直接进行调用将耗费大量资源,进而使应用程序的性能受损。 在最坏的情况下,将发生导致应用程序中出现死锁的情况,进而使执行冻结。

不过,在有些情况下,您可能需要通过线程调用控件的方法。 例如,您可能要在窗体上调用一个禁用按钮或更新显示的方法来响应某个线程执行的操作。 .NET Framework 提供从任何线程都可安全调用的方法,以调用与其他线程所拥有的控件进行交互的方法。 Invoke 方法允许同步执行控件上的方法,而 BeginInvoke 方法则初始化异步执行。 要使用这些方法,必须用与将调用的方法相同的签名声明委托。 然后,您可以通过向要调用的方法提供适当的委托来调用窗体上任何控件的 InvokeBeginInvoke 方法。 任何必需的参数都包装在 Object 中,并被传输到该方法。

调用涉及其他线程所拥有的控件的方法

  1. 用与要调用的方法相同的签名声明一个委托。

    下面的示例显示如何使用 Integer 和 String 参数声明委托。

    Public Delegate Sub myDelegate(ByVal anInteger as Integer, ByVal _
       aString as String)
    
    public delegate void myDelegate(int anInteger, string aString);
    
  2. 使用任何控件来调用对其他线程所拥有的控件进行操作的方法。

    备注

    方法所需的参数(如果有)可在 Object 中提供。

    • 如果要同步调用方法,请调用 Control.Invoke 方法

      Label1.Invoke(New myDelegate(AddressOf myMethod), New _
         Object() {1, "This is the string"})
      
      Label1.Invoke(new myDelegate(myMethod), new Object[] {1,
         "This is the string"});
      
    • 如果要异步调用方法,请调用 Control.BeginInvoke 方法

      Label1.BeginInvoke(New myDelegate(AddressOf myMethod), _
         New Object() {1, "This is the string"})
      
      Label1.BeginInvoke(new myDelegate(myMethod), new 
      Object[] {1, "This is the string"});
      

请参见

任务

演练:用 Visual Basic 创作简单的多线程组件

演练:使用 Visual C# 创作简单的多线程组件

参考

BackgroundWorker

概念

基于事件的异步模式概述

其他资源

组件中的多线程处理