Interesting about the implementation of Control.Invoke ()

What exactly does Control.Invoke (delegate) do to get the delegate to work in the GUI thread? In addition, my understanding is that invoke will block until the called function is executed. How is this achieved?

I would like to get some nice detailed details. I hope to find out something interesting.

+7
source share
2 answers

Edit: The control implements the ISynchronizeInvoke interface. You can do the same effect with SynchronizationContext and call Post when invoke invocation. 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 research using Reflector shows that Invoke uses some native API calls to achieve this:

 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; } 
+4
source

If I want to know the insides, I usually run ILSpy and look at the decompiled BCL sources. Alternatively, you can download Mono or Rotor sources.

+1
source

All Articles