Curious about the implementation of Control.Invoke()

走远了吗. 提交于 2019-12-01 16:40:21

Edit: The control implements ISynchronizeInvoke interface, You can make the same effect using the SynchronizationContext and call Post when you call Invoke. something like:

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

Further investigation using Reflector shows that the Invoke uses some native API calls to achieve that:

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

If I want to know internals, I usually fire up ILSpy and look at the decompiled sources of the BCL. Alternatively, you could download the Mono or the Rotor sources.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!