然后,通过委托进行同步或异步调用:
AsyncInvokeDel calculateAction = cal.Calculate; 
string resultStrAction = string.Empty; 
// int result1 = calculateAction.Invoke(123, 456, ref resultStrAction); 
IAsyncResult calculateResult1 = calculateAction.BeginInvoke(123, 456, ref resultStrAction, null, null); 
int result1 = calculateAction.EndInvoke(ref resultStrAction, calculateResult1);

  三、多线程操作控件

  访问 Windows 窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用情况和死锁。确保以线程安全方式访问控件非常重要。

  不过,在有些情况下,您可能需要多线程调用控件的方法。.NET Framework 提供了从任何线程操作控件的方式:

  1、非安全方式访问控件(此方式请永远不要再使用)

  多线程访问窗口中的控件,可以在窗口的构造函数中将Form的CheckForIllegalCrossThreadCalls静态属性设置为false。
// 获取或设置一个值,该值指示是否捕获对错误线程的调用, 
// 这些调用在调试应用程序时访问控件的System.Windows.Forms.Control.Handle属性。 
// 如果捕获了对错误线程的调用,则为 true;否则为 false。 
public static bool CheckForIllegalCrossThreadCalls { get; set; }

  2、安全方式访问控件

  原理:从一个线程封送调用并跨线程边界将其发送到另一个线程,并将调用插入到创建控件线程的消息队列中,当控件创建线程处理这个消息时,会在自己的上下文中执行传入的方法。(此过程只有调用线程和创建控件线程,并没有创建新线程)

  注意:从一个线程封送调用并跨线程边界将其发送到另一个线程会耗费大量的系统资源,所以应避免重复调用其他线程上的控件。

  1)使用BackgroundWork后台辅助线程控件控件(AsyncOperationManager类和AsyncOperation类帮助器方式)。

  2)结合TaskScheduler.FromCurrentSynchronizationContext() 和Task 实现。

  3)使用Control类上提供的Invoke 和BeginInvoke方法。

  因本文主要解说IAsyncResult异步编程模式,所以只详细分析Invoke 和BeginInvoke跨线程访问控件方式。

  Control类实现了ISynchronizeInvoke接口,提供了Invoke和BeginInvoke方法来支持其它线程更新GUI界面控件的机制。
public interface ISynchronizeInvoke 

    // 获取一个值,该值指示调用线程是否与控件的创建线程相同。 
    bool InvokeRequired { get; } 
    // 在控件创建的线程上异步执行指定委托。 
    AsyncResult BeginInvoke(Delegate method, params object[] args); 
    object EndInvoke(IAsyncResult asyncResult); 
    // 在控件创建的线程上同步执行指定委托。 
    object Invoke(Delegate method, params object[] args); 
}