2011-08-04 27 views
7

Control.Invoke(Delegate)做了什麼來讓委託在GUI線程上運行?此外,我的理解是,調用將阻塞,直到被調用的函數完成。它是如何實現的?對Control.Invoke()的實現感到好奇

我想要一些不錯的細節。我希望學習一些有趣的東西。

+0

檢查[this] [1] out。 [1]:http://stackoverflow.com/questions/4514273/does-control-invoke-pump-messages – n8wrl

回答

4

編輯:該控件實現了ISynchronizeInvoke接口,您可以使用SynchronizationContext產生相同的效果,並在致電Invoke時致電Post。是這樣的:

public object Invoke(Delegate method, object[] args) 
{ 
    if (method == null) 
    { 
     throw new ArgumentNullException("method"); 
    } 

    object objectToGet = null; 

    SendOrPostCallback invoker = new SendOrPostCallback(
    delegate(object data) 
    { 
     objectToGet = method.DynamicInvoke(args); 
    }); 

    _currentContext.Send(new SendOrPostCallback(invoker), method.Target); 

    return objectToGet; 
} 

進一步調查使用反射表明Invoke使用了一些本地的API調用來實現這一目標:

private object MarshaledInvoke(Control caller, Delegate method, object[] args, bool synchronous) 
{ 
    int num; 
    if (!this.IsHandleCreated) 
    { 
     throw new InvalidOperationException(SR.GetString("ErrorNoMarshalingThread")); 
    } 
    if (((ActiveXImpl) this.Properties.GetObject(PropActiveXImpl)) != null) 
    { 
     IntSecurity.UnmanagedCode.Demand(); 
    } 
    bool flag = false; 
    if ((SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(this, this.Handle), out num) == SafeNativeMethods.GetCurrentThreadId()) && synchronous) 
    { 
     flag = true; 
    } 
    ExecutionContext executionContext = null; 
    if (!flag) 
    { 
     executionContext = ExecutionContext.Capture(); 
    } 
    ThreadMethodEntry entry = new ThreadMethodEntry(caller, this, method, args, synchronous, executionContext); 
    lock (this) 
    { 
     if (this.threadCallbackList == null) 
     { 
      this.threadCallbackList = new Queue(); 
     } 
    } 
    lock (this.threadCallbackList) 
    { 
     if (threadCallbackMessage == 0) 
     { 
      threadCallbackMessage = SafeNativeMethods.RegisterWindowMessage(Application.WindowMessagesVersion + "_ThreadCallbackMessage"); 
     } 
     this.threadCallbackList.Enqueue(entry); 
    } 
    if (flag) 
    { 
     this.InvokeMarshaledCallbacks(); 
    } 
    else 
    { 
     UnsafeNativeMethods.PostMessage(new HandleRef(this, this.Handle), threadCallbackMessage, IntPtr.Zero, IntPtr.Zero); 
    } 
    if (!synchronous) 
    { 
     return entry; 
    } 
    if (!entry.IsCompleted) 
    { 
     this.WaitForWaitHandle(entry.AsyncWaitHandle); 
    } 
    if (entry.exception != null) 
    { 
     throw entry.exception; 
    } 
    return entry.retVal; 
} 
1

如果我想知道的內部,我通常火了ILSpy,並期待在經過反編譯的BCL資源。或者,您可以下載MonoRotor來源。

+2

或者使用反射器;) – Abel

+0

你不說壞的 「R」 字! ;-) –

+0

如果Reflector的許可證發生變化,我開始使用Telerik的反編譯器並且像這樣:http://www.keepdecompilingfree.com – Jamey