Control.Invoke(Delegate)は、デリゲートをGUIスレッド上で実行するために正確に何をしますか?さらに、呼び出された関数が完了するまで、呼び出しはブロックされます。どのようにこれを達成するのですか?Control.Invoke()の実装について気になる
私はいくつか良いぎっしりした詳細が欲しいです。興味深いことを学びたいと思っています。
Control.Invoke(Delegate)は、デリゲートをGUIスレッド上で実行するために正確に何をしますか?さらに、呼び出された関数が完了するまで、呼び出しはブロックされます。どのようにこれを達成するのですか?Control.Invoke()の実装について気になる
私はいくつか良いぎっしりした詳細が欲しいです。興味深いことを学びたいと思っています。
編集:コントロールは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]をチェックしてください。 [1]:http://stackoverflow.com/questions/4514273/does-control-invoke-pump-messages – n8wrl