对Control.Invoke()的实现感到好奇

时间:2011-08-04 21:19:00

标签: .net winforms invoke

Control.Invoke(Delegate)究竟做了什么来让代理在GUI线程上运行?此外,我的理解是invoke将阻塞,直到被调用的函数完成。它是如何实现这一目标的?

我想要一些好的细节。我希望学到一些有趣的东西。

2 个答案:

答案 0 :(得分:4)

编辑:控件实现ISynchronizeInvoke界面,您可以使用SynchronizationContext发挥相同效果,并在致电Post时致电Invoke。类似的东西:

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;
}

答案 1 :(得分:1)

如果我想知道内部,我通常会启动ILSpy并查看BCL的反编译源。或者,您可以下载MonoRotor来源。