【发布时间】:2011-08-05 05:31:17
【问题描述】:
Control.Invoke(Delegate) 究竟做了什么来让委托在 GUI 线程上运行?此外,我的理解是调用将阻塞,直到调用的函数完成。它是如何做到这一点的?
我想要一些好的细节。我希望能学到一些有趣的东西。
【问题讨论】:
-
检查 [this][1]。 [1]:stackoverflow.com/questions/4514273/…
Control.Invoke(Delegate) 究竟做了什么来让委托在 GUI 线程上运行?此外,我的理解是调用将阻塞,直到调用的函数完成。它是如何做到这一点的?
我想要一些好的细节。我希望能学到一些有趣的东西。
【问题讨论】:
编辑:该控件实现了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;
}
使用 Reflector 的进一步调查表明,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;
}
【讨论】:
【讨论】: