C#:Control.BeginInvoke() 源码调用记录


        [EditorBrowsable(EditorBrowsableState.Advanced)] 
        [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
        public IAsyncResult BeginInvoke(Delegate method, params Object[] args) { 
            using (new MultithreadSafeCallScope()) {
                Control marshaler = FindMarshalingControl();
                return(IAsyncResult)marshaler.MarshaledInvoke(this, method, args, false);
            } 
        }

        private Control FindMarshalingControl() { 
            //
            lock(this) { 
                Control c = this;

                while (c != null && !c.IsHandleCreated) {
                    Control p = c.ParentInternal; 
                    c = p;
                } 
 
                if (c == null) {
                    // No control with a created handle.  We 
                    // just use our own control.  MarshaledInvoke
                    // will throw an exception because there
                    // is no handle.
                    // 
                    c = this;
                } 
                else { 
                    Debug.Assert(c.IsHandleCreated, "FindMarshalingControl chose a bad control.");
                } 

                return(Control)c;
            }
        } 

        private Object MarshaledInvoke(Control caller, Delegate method, Object[] args, bool synchronous) { 

            // Marshaling an invoke occurs in three steps:
            //
            // 1.  Create a ThreadMethodEntry that contains the packet of information 
            //     about this invoke.  This TME is placed on a linked list of entries because
            //     we have a gap between the time we PostMessage and the time it actually 
            //     gets processed, and this gap may allow other invokes to come in.  Access 
            //     to this linked list is always synchronized.
            // 
            // 2.  Post ourselves a message.  Our caller has already determined the
            //     best control to call us on, and we should almost always have a handle.
            //
            // 3.  If we're synchronous, wait for the message to get processed.  We don't do 
            //     a SendMessage here so we're compatible with OLE, which will abort many
            //     types of calls if we're within a SendMessage. 
            // 

            if (!IsHandleCreated) { 
                throw new InvalidOperationException(SR.GetString(SR.ErrorNoMarshalingThread));
            }

            // We have to demand unmanaged code permission here for the control hosted in 
            // the browser case. Without this check, we will expose a security hole, because
            // ActiveXImpl.OnMessage() will assert unmanaged code for everyone as part of 
            // its implementation. 
            // The right fix is to remove the Assert() on top of the ActiveXImpl class, and
            // visit each method to see if it needs unmanaged code permission, and if so, add 
            // the permission just to that method(s).
            //
            ActiveXImpl activeXImpl = (ActiveXImpl)Properties.GetObject(PropActiveXImpl);
            if (activeXImpl != null) { 
                IntSecurity.UnmanagedCode.Demand();
            } 
 
            // We don't want to wait if we're on the same thread, or else we'll deadlock.
            // It is important that syncSameThread always be false for asynchronous calls. 
            //
            bool syncSameThread = false;
            int pid; // ignored
            if (SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(this, Handle), out pid) == SafeNativeMethods.GetCurrentThreadId()) { 
                if (synchronous)
                    syncSameThread = true; 
            } 

            // Store the compressed stack information from the thread that is calling the Invoke() 
            // so we can assign the same security context to the thread that will actually execute
            // the delegate being passed.
            //
            ExecutionContext executionContext = null; 
            if (!syncSameThread) {
                executionContext = ExecutionContext.Capture(); 
            } 
            ThreadMethodEntry tme = new ThreadMethodEntry(caller, method, args, synchronous, executionContext);
 
            lock (this) {
                if (threadCallbackList == null) {
                    threadCallbackList = new Queue();
                } 
            }
 
            lock (threadCallbackList) { 
                if (threadCallbackMessage == 0) {
                    threadCallbackMessage = SafeNativeMethods.RegisterWindowMessage(Application.WindowMessagesVersion + "_ThreadCallbackMessage"); 
                }
                threadCallbackList.Enqueue(tme);
            }
 
            if (syncSameThread) {
                InvokeMarshaledCallbacks(); 
            }  else { 
                //
 
                UnsafeNativeMethods.PostMessage(new HandleRef(this, Handle), threadCallbackMessage, IntPtr.Zero, IntPtr.Zero);
            }

            if (synchronous) { 
                if (!tme.IsCompleted) {
                    WaitForWaitHandle(tme.AsyncWaitHandle); 
                } 
                if (tme.exception != null) {
                    throw tme.exception; 
                }
                return tme.retVal;
            }
            else { 
                return(IAsyncResult)tme;
            } 
        } 

c#源码查看网址:

https://referencesource.microsoft.com/

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值