2011-08-04 27 views
7

Control.Invoke(Delegate)は、デリゲートをGUIスレッド上で実行するために正確に何をしますか?さらに、呼び出された関数が完了するまで、呼び出しはブロックされます。どのようにこれを達成するのですか?Control.Invoke()の実装について気になる

私はいくつか良いぎっしりした詳細が欲しいです。興味深いことを学びたいと思っています。

+0

[こちら] [1]をチェックしてください。 [1]:http://stackoverflow.com/questions/4514273/does-control-invoke-pump-messages – n8wrl

答えて

4

編集:コントロールは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の逆コンパイルされたソース。また、MonoまたはRotorソースをダウンロードすることもできます。

+2

かリフレクターを使用しています。) – Abel

+0

あなたが悪い "R" の単語を言ってはいけません! ;-) –

+0

Reflectorのライセンスが変更された場合、私はTelerikの逆コンパイラを使い始めました:http://www.keepdecompilingfree.com – Jamey

関連する問題