Control.Invoke(Delegate)做了什麼來讓委託在GUI線程上運行?此外,我的理解是,調用將阻塞,直到被調用的函數完成。它是如何實現的?對Control.Invoke()的實現感到好奇
我想要一些不錯的細節。我希望學習一些有趣的東西。
Control.Invoke(Delegate)做了什麼來讓委託在GUI線程上運行?此外,我的理解是,調用將阻塞,直到被調用的函數完成。它是如何實現的?對Control.Invoke()的實現感到好奇
我想要一些不錯的細節。我希望學習一些有趣的東西。
編輯:該控件實現了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;
}
檢查[this] [1] out。 [1]:http://stackoverflow.com/questions/4514273/does-control-invoke-pump-messages – n8wrl