1)Control类的 Invoke,BeginInvoke 内部实现如下:

  a)Invoke (同步调用)先判断控件创建线程与当前线程是否相同,相同则直接调用委托方法;否则使用Win32API的PostMessage 异步执行。

  b)BeginInvoke (异步调用)使用Win32API的PostMessage 异步执行
UnsafeNativeMethods.PostMessage(new HandleRef(this, this.Handle) 
                  , threadCallbackMessage, IntPtr.Zero, IntPtr.Zero); 
[DllImport("user32.dll", CharSet=CharSet.Auto)] 
public static extern bool PostMessage(HandleRefhwnd, intmsg, IntPtrwparam, IntPtrlparam);

  PostMessage 是windows api,用来把一个消息发送到一个窗口的消息队列。这个方法是异步的,也是该方法封送完毕后马上返回,不会等待委托方法的执行结束,调用者线程将不会被阻塞。(对应同步方法的windows api是:SendMessage())

  2)InvokeRequired

  获取一个值,该值指示调用线程是否与控件的创建线程相同。内部关键如下:
Int windowThreadProcessId = SafeNativeMethods.GetWindowThreadProcessId(ref2, out num); 
Int currentThreadId = SafeNativeMethods.GetCurrentThreadId(); 
return (windowThreadProcessId != currentThreadId);

  即返回“通过GetWindowThreadProcessId功能函数得到创建指定窗口线程的标识和创建窗口的进程的标识符与当前线程Id进行比较”的结果。

  3)示例(详见示例文件)

  在使用的时候,我们使用 this.InvokeRequired 属性来判断是使用Invoke或BeginInvoke 还是直接调用方法。
private void InvokeControl(object mainThreadId) 

    if (this.InvokeRequired) 
    { 
        this.Invoke(new Action<String>(ChangeText), "InvokeRequired = true.改变控件Text值"); 
        //this.textBox1.Invoke(new Action<int>(InvokeCount), (int)mainThreadId); 
    } 
    else
    { 
        ChangeText("在创建控件的线程上,改变控件Text值"); 
    } 

  
private void ChangeText(String str) 

    this.textBox1.Text += str; 
}

  注意,在InvokeControl方法中使用 this.Invoke(Delegate del) 和使用 this.textBox1.Invoke(Delegate del) 效果是一样的。因为在执行Invoke或BeginInvoke时,内部首先调用 FindMarshalingControl() 进行一个循环向上回溯,从当前控件开始回溯父控件,直到找到的父控件,用它作为封送对象。也是说 this.textBox1.Invoke(Delegate del) 会追溯到和 this.Invoke(Delegate del) 一样的起点。(子控件的创建线程一定是创建父控件的线程,所以这种追溯不会导致将调用封送到错误的目的线程)

  本节到此结束,本节主要讲了异步编程模式之一“异步编程模型(APM)”,是基于IAsyncResult设计模式实现的异步编程方式,并且构建了一个继承自IAsyncResult接口的示例,及展示了这种模式在委托及跨线程访问控件上的经典应用。