DispatcherOperation.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Base / System / Windows / Threading / DispatcherOperation.cs / 1 / DispatcherOperation.cs

                            using System; 
using System.Security;
using System.Security.Permissions;
using System.Threading;
 
namespace System.Windows.Threading
{ 
    ///  
    ///     DispatcherOperation represents a delegate that has been
    ///     posted to the Dispatcher queue. 
    /// 
    public sealed class DispatcherOperation
    {
        ///  
        ///    Critical: This code calls into InvokeInSecurityContext which can be used to process input
        ///    TreatAsSafe: This is ok to expose since the operation itself is ok . But this will 
        ///                 `blow up if something untowards is done in the operation that violates trust boundaries 
        ///                 .Essentially although this lets you execute arbitrary code that code cannot be doing
        ///                 any untrusted operation 
        /// 
        [SecurityCritical,SecurityTreatAsSafe]
        static DispatcherOperation()
        { 
            _invokeInSecurityContext = new ContextCallback(InvokeInSecurityContext);
        } 
 
        /// 
        ///     Critical: accesses _executionContext 
        /// 
        [SecurityCritical]
        internal DispatcherOperation(
            Dispatcher dispatcher, 
            Delegate method,
            DispatcherPriority priority, // NOTE: should be Priority 
            object args, 
            bool isSingleParameter)
        { 
            _dispatcher = dispatcher;
            _method = method;
            _priority = priority;
            _isSingleParameter = isSingleParameter; 
            _args = args;
 
            _executionContext = ExecutionContext.Capture(); 
        }
 

        /// 
        /// Internal constructor used to generate a Dispatcher operation
        /// when the dispatcher has shut down 
        /// 
        ///  
        ///  
        /// 
        internal DispatcherOperation( 
            Dispatcher dispatcher,
            Delegate method,
            DispatcherPriority priority
            ) 
        {
            _dispatcher = dispatcher; 
            _method = method; 
            _priority = priority;
            _status = DispatcherOperationStatus.Aborted; 
        }

        /// 
        ///     Returns the Dispatcher that this operation was posted to. 
        /// 
        public Dispatcher Dispatcher 
        { 
            get
            { 
                return _dispatcher;
            }
        }
 
        /// 
        ///     Gets or sets the priority of this operation within the 
        ///     Dispatcher queue. 
        /// 
        public DispatcherPriority Priority // NOTE: should be Priority 
        {
            get
            {
                return _priority; 
            }
 
            set 
            {
                Dispatcher.ValidatePriority(value, "value"); 

                if(value != _priority && _dispatcher.SetPriority(this, value))
                {
                    _priority = value; 
                }
            } 
        } 

        ///  
        ///     The status of this operation.
        /// 
        public DispatcherOperationStatus Status
        { 
            get
            { 
                return _status; 
            }
        } 

        /// 
        ///     Waits for this operation to complete.
        ///  
        /// 
        ///     The status of the operation.  To obtain the return value 
        ///     of the invoked delegate, use the the Result property. 
        /// 
        public DispatcherOperationStatus Wait() 
        {
            return Wait(TimeSpan.FromMilliseconds(-1));
        }
 
        /// 
        ///     Waits for this operation to complete. 
        ///  
        /// 
        ///     The maximum amount of time to wait. 
        /// 
        /// 
        ///     The status of the operation.  To obtain the return value
        ///     of the invoked delegate, use the the Result property. 
        /// 
        ///  
        ///    Critical: This code calls into PushFrame which has a link demand 
        ///    PublicOk: The act of setting a timeline for an operation to complete is a safe one
        ///  
        [SecurityCritical]
        public DispatcherOperationStatus Wait(TimeSpan timeout)
        {
            if((_status == DispatcherOperationStatus.Pending || _status == DispatcherOperationStatus.Executing) && 
                timeout.TotalMilliseconds != 0)
            { 
                if(_dispatcher.Thread == Thread.CurrentThread) 
                {
                    if(_status == DispatcherOperationStatus.Executing) 
                    {
                        // We are the dispatching thread, and the current operation state is
                        // executing, which means that the operation is in the middle of
                        // executing (on this thread) and is trying to wait for the execution 
                        // to complete.  Unfortunately, the thread will now deadlock, so
                        // we throw an exception instead. 
                        throw new InvalidOperationException(SR.Get(SRID.ThreadMayNotWaitOnOperationsAlreadyExecutingOnTheSameThread)); 
                    }
 
                    // We are the dispatching thread for this operation, so
                    // we can't block.  We will push a frame instead.
                    DispatcherOperationFrame frame = new DispatcherOperationFrame(this, timeout);
                    Dispatcher.PushFrame(frame); 
                }
                else 
                { 
                    // We are some external thread, so we can just block.  Of
                    // course this means that the Dispatcher (queue)for this 
                    // thread (if any) is now blocked.  The COM STA model
                    // suggests that we should pump certain messages so that
                    // back-communication can happen.  Underneath us, the CLR
                    // will pump the STA apartment for us, and we will allow 
                    // the UI thread for a context to call
                    // Invoke(Priority.Max, ...) without going through the 
                    // blocked queue. 
                    DispatcherOperationEvent wait = new DispatcherOperationEvent(this, timeout);
                    wait.WaitOne(); 
                }
            }

            return _status; 
        }
 
        ///  
        ///     Aborts this operation.
        ///  
        /// 
        ///     False if the operation could not be aborted (because the
        ///     operation was already in  progress)
        ///  
        public bool Abort()
        { 
            bool removed = false; 

            if (_dispatcher != null) 
            {
                removed = _dispatcher.Abort(this);

                if (removed) 
                {
                    // Raise the Aborted so anyone who is waiting will wake up. 
                    EventHandler aborted = _aborted; 
                    if (aborted != null)
                    { 
                        aborted(this, EventArgs.Empty);
                    }
                }
            } 

            return removed; 
        } 

        ///  
        ///     Name of this operation.
        /// 
        /// 
        ///     Returns a string representation of the operation to be invoked. 
        /// 
        internal String Name 
        { 
            get
            { 
                return _method.Method.DeclaringType + "." + _method.Method.Name;
            }
        }
 
        /// 
        ///     Returns the result of the operation if it has completed. 
        ///  
        public object Result
        { 
            get
            {
                return _result;
            } 
        }
 
        ///  
        ///     An event that is raised when the operation is aborted.
        ///  
        public event EventHandler Aborted
        {
            add
            { 
                lock (DispatcherLock)
                { 
                    _aborted = (EventHandler) Delegate.Combine(_aborted, value); 
                }
            } 

            remove
            {
                lock(DispatcherLock) 
                {
                    _aborted = (EventHandler) Delegate.Remove(_aborted, value); 
                } 
            }
        } 

        /// 
        ///     An event that is raised when the operation completes.
        ///  
        public event EventHandler Completed
        { 
            add 
            {
                lock (DispatcherLock) 
                {
                    _completed = (EventHandler) Delegate.Combine(_completed, value);
                }
            } 

            remove 
            { 
                lock(DispatcherLock)
                { 
                    _completed = (EventHandler) Delegate.Remove(_completed, value);
                }
            }
        } 

        // Note: this is called by the Dispatcher to actually invoke the operation. 
        // Invoke --> InvokeInSecurityContext --> InvokeImpl 
        /// 
        ///    Critical: This code calls into ExecutionContext.Run which is link demand protected 
        ///              accesses _executionContext
        /// 
        [SecurityCritical]
        internal object Invoke() 
        {
            // Mark this operation as executing. 
            _status = DispatcherOperationStatus.Executing; 

            // Continue using the execution context that was active when the operation 
            // was begun.
            if(_executionContext != null)
            {
                ExecutionContext.Run(_executionContext, _invokeInSecurityContext, this); 
            }
            else 
            { 
                // _executionContext can be null if someone called
                // ExecutionContext.SupressFlow before calling BeginInvoke/Invoke. 
                // In this case we'll just call the invokation directly.
                // SupressFlow is a privileged operation, so this is not a
                // security hole.
                _invokeInSecurityContext(this); 
            }
 
            // This block of code needs to be synchronized with the constructor of 
            // DispatcherOperationEvent which may be called through
            // Dispatcher.Invoke on a separate thread. 

            EventHandler completed;
            lock(DispatcherLock)
            { 
                // Mark this operation as completed.
                _status = DispatcherOperationStatus.Completed; 
 
                // Read the Completed event handler.
                completed = _completed; 
            }

            // Raise the Completed so anyone who is waiting will wake up.
            if(completed != null) 
            {
                completed(this, EventArgs.Empty); 
            } 

            return _result; 
        }

        // Invoke --> InvokeInSecurityContext --> InvokeImpl
        ///  
        ///     Critical: This code can execute arbitrary code
        ///  
        [SecurityCritical] 
        private static void InvokeInSecurityContext(Object state)
        { 
            DispatcherOperation operation = (DispatcherOperation) state;
            operation.InvokeImpl();
        }
 
        // Invoke --> InvokeInSecurityContext --> InvokeImpl
        ///  
        ///     Critical: This code calls into SynchronizationContext.SetSynchronizationContext which link demands 
        /// 
        [SecurityCritical] 
        private void InvokeImpl()
        {
            SynchronizationContext oldSynchronizationContext = SynchronizationContext.Current;
 
            try
            { 
                // We are executing under the "foreign" execution context, but the 
                // SynchronizationContext must be for the correct dispatcher.
                SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(_dispatcher)); 

                // Invoke the delegate that does the work for this operation.
                _result = _dispatcher.WrappedInvoke(_method, _args, _isSingleParameter);
            } 
            finally
            { 
                SynchronizationContext.SetSynchronizationContext(oldSynchronizationContext); 
            }
        } 

        private class DispatcherOperationFrame : DispatcherFrame
        {
            // Note: we pass "exitWhenRequested=false" to the base 
            // DispatcherFrame construsctor because we do not want to exit
            // this frame if the dispatcher is shutting down. This is 
            // because we may need to invoke operations during the shutdown process. 
            public DispatcherOperationFrame(DispatcherOperation op, TimeSpan timeout) : base(false)
            { 
                _operation = op;

                // We will exit this frame once the operation is completed or aborted.
                _operation.Aborted += new EventHandler(OnCompletedOrAborted); 
                _operation.Completed += new EventHandler(OnCompletedOrAborted);
 
                // We will exit the frame if the operation is not completed within 
                // the requested timeout.
                if(timeout.TotalMilliseconds > 0) 
                {
                    _waitTimer = new Timer(new TimerCallback(OnTimeout),
                                           null,
                                           timeout, 
                                           TimeSpan.FromMilliseconds(-1));
                } 
 
                // Some other thread could have aborted the operation while we were
                // setting up the handlers.  We check the state again and mark the 
                // frame as "should not continue" if this happened.
                if(_operation._status != DispatcherOperationStatus.Pending)
                {
                    Exit(); 
                }
 
            } 

            private void OnCompletedOrAborted(object sender, EventArgs e) 
            {
                Exit();
            }
 
            private void OnTimeout(object arg)
            { 
                Exit(); 
            }
 
            private void Exit()
            {
                Continue = false;
 
                if(_waitTimer != null)
                { 
                    _waitTimer.Dispose(); 
                }
 
                _operation.Aborted -= new EventHandler(OnCompletedOrAborted);
                _operation.Completed -= new EventHandler(OnCompletedOrAborted);
            }
 
            private DispatcherOperation _operation;
            private Timer _waitTimer; 
        } 

        private class DispatcherOperationEvent 
        {
            public DispatcherOperationEvent(DispatcherOperation op, TimeSpan timeout)
            {
                _operation = op; 
                _timeout = timeout;
                _event = new ManualResetEvent(false); 
                _eventClosed = false; 

                lock(DispatcherLock) 
                {
                    // We will set our event once the operation is completed or aborted.
                    _operation.Aborted += new EventHandler(OnCompletedOrAborted);
                    _operation.Completed += new EventHandler(OnCompletedOrAborted); 

                    // Since some other thread is dispatching this operation, it could 
                    // have been dispatched while we were setting up the handlers. 
                    // We check the state again and set the event ourselves if this
                    // happened. 
                    if(_operation._status != DispatcherOperationStatus.Pending && _operation._status != DispatcherOperationStatus.Executing)
                    {
                        _event.Set();
                    } 
                }
            } 
 
            private void OnCompletedOrAborted(object sender, EventArgs e)
            { 
                lock(DispatcherLock)
                {
                    if(!_eventClosed)
                    { 
                        _event.Set();
                    } 
                } 
            }
 
            public void WaitOne()
            {
                _event.WaitOne(_timeout, false);
 
                lock(DispatcherLock)
                { 
                    if(!_eventClosed) 
                    {
                        // Cleanup the events. 
                        _operation.Aborted -= new EventHandler(OnCompletedOrAborted);
                        _operation.Completed -= new EventHandler(OnCompletedOrAborted);

                        // Close the event immediately instead of waiting for a GC 
                        // because the Dispatcher is a a high-activity component and
                        // we could run out of events. 
                        _event.Close(); 

                        _eventClosed = true; 
                    }
                }
            }
 
            private object DispatcherLock
            { 
                get { return _operation.DispatcherLock; } 
            }
 
            private DispatcherOperation _operation;
            private TimeSpan _timeout;
            private ManualResetEvent _event;
            private bool _eventClosed; 
        }
 
        private object DispatcherLock 
        {
            get { return _dispatcher._instanceLock; } 
        }

        /// 
        ///     Obtained under an elevation. 
        /// 
        [SecurityCritical] 
        private ExecutionContext _executionContext; 
        private static ContextCallback _invokeInSecurityContext;
 
        private Dispatcher _dispatcher;
        private DispatcherPriority _priority; // NOTE: should be Priority
        private Delegate _method;
        private object _args; 

        private bool _isSingleParameter; 
 
        internal DispatcherOperationStatus _status; // set from Dispatcher
        private object _result; 

        internal PriorityItem _item; // The Dispatcher sets this when it enques/deques the item.

        EventHandler _aborted; 
        EventHandler _completed;
    } 
 
    /// 
    ///     A convenient delegate to use for dispatcher operations. 
    /// 
    public delegate object DispatcherOperationCallback(object arg);
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System; 
using System.Security;
using System.Security.Permissions;
using System.Threading;
 
namespace System.Windows.Threading
{ 
    ///  
    ///     DispatcherOperation represents a delegate that has been
    ///     posted to the Dispatcher queue. 
    /// 
    public sealed class DispatcherOperation
    {
        ///  
        ///    Critical: This code calls into InvokeInSecurityContext which can be used to process input
        ///    TreatAsSafe: This is ok to expose since the operation itself is ok . But this will 
        ///                 `blow up if something untowards is done in the operation that violates trust boundaries 
        ///                 .Essentially although this lets you execute arbitrary code that code cannot be doing
        ///                 any untrusted operation 
        /// 
        [SecurityCritical,SecurityTreatAsSafe]
        static DispatcherOperation()
        { 
            _invokeInSecurityContext = new ContextCallback(InvokeInSecurityContext);
        } 
 
        /// 
        ///     Critical: accesses _executionContext 
        /// 
        [SecurityCritical]
        internal DispatcherOperation(
            Dispatcher dispatcher, 
            Delegate method,
            DispatcherPriority priority, // NOTE: should be Priority 
            object args, 
            bool isSingleParameter)
        { 
            _dispatcher = dispatcher;
            _method = method;
            _priority = priority;
            _isSingleParameter = isSingleParameter; 
            _args = args;
 
            _executionContext = ExecutionContext.Capture(); 
        }
 

        /// 
        /// Internal constructor used to generate a Dispatcher operation
        /// when the dispatcher has shut down 
        /// 
        ///  
        ///  
        /// 
        internal DispatcherOperation( 
            Dispatcher dispatcher,
            Delegate method,
            DispatcherPriority priority
            ) 
        {
            _dispatcher = dispatcher; 
            _method = method; 
            _priority = priority;
            _status = DispatcherOperationStatus.Aborted; 
        }

        /// 
        ///     Returns the Dispatcher that this operation was posted to. 
        /// 
        public Dispatcher Dispatcher 
        { 
            get
            { 
                return _dispatcher;
            }
        }
 
        /// 
        ///     Gets or sets the priority of this operation within the 
        ///     Dispatcher queue. 
        /// 
        public DispatcherPriority Priority // NOTE: should be Priority 
        {
            get
            {
                return _priority; 
            }
 
            set 
            {
                Dispatcher.ValidatePriority(value, "value"); 

                if(value != _priority && _dispatcher.SetPriority(this, value))
                {
                    _priority = value; 
                }
            } 
        } 

        ///  
        ///     The status of this operation.
        /// 
        public DispatcherOperationStatus Status
        { 
            get
            { 
                return _status; 
            }
        } 

        /// 
        ///     Waits for this operation to complete.
        ///  
        /// 
        ///     The status of the operation.  To obtain the return value 
        ///     of the invoked delegate, use the the Result property. 
        /// 
        public DispatcherOperationStatus Wait() 
        {
            return Wait(TimeSpan.FromMilliseconds(-1));
        }
 
        /// 
        ///     Waits for this operation to complete. 
        ///  
        /// 
        ///     The maximum amount of time to wait. 
        /// 
        /// 
        ///     The status of the operation.  To obtain the return value
        ///     of the invoked delegate, use the the Result property. 
        /// 
        ///  
        ///    Critical: This code calls into PushFrame which has a link demand 
        ///    PublicOk: The act of setting a timeline for an operation to complete is a safe one
        ///  
        [SecurityCritical]
        public DispatcherOperationStatus Wait(TimeSpan timeout)
        {
            if((_status == DispatcherOperationStatus.Pending || _status == DispatcherOperationStatus.Executing) && 
                timeout.TotalMilliseconds != 0)
            { 
                if(_dispatcher.Thread == Thread.CurrentThread) 
                {
                    if(_status == DispatcherOperationStatus.Executing) 
                    {
                        // We are the dispatching thread, and the current operation state is
                        // executing, which means that the operation is in the middle of
                        // executing (on this thread) and is trying to wait for the execution 
                        // to complete.  Unfortunately, the thread will now deadlock, so
                        // we throw an exception instead. 
                        throw new InvalidOperationException(SR.Get(SRID.ThreadMayNotWaitOnOperationsAlreadyExecutingOnTheSameThread)); 
                    }
 
                    // We are the dispatching thread for this operation, so
                    // we can't block.  We will push a frame instead.
                    DispatcherOperationFrame frame = new DispatcherOperationFrame(this, timeout);
                    Dispatcher.PushFrame(frame); 
                }
                else 
                { 
                    // We are some external thread, so we can just block.  Of
                    // course this means that the Dispatcher (queue)for this 
                    // thread (if any) is now blocked.  The COM STA model
                    // suggests that we should pump certain messages so that
                    // back-communication can happen.  Underneath us, the CLR
                    // will pump the STA apartment for us, and we will allow 
                    // the UI thread for a context to call
                    // Invoke(Priority.Max, ...) without going through the 
                    // blocked queue. 
                    DispatcherOperationEvent wait = new DispatcherOperationEvent(this, timeout);
                    wait.WaitOne(); 
                }
            }

            return _status; 
        }
 
        ///  
        ///     Aborts this operation.
        ///  
        /// 
        ///     False if the operation could not be aborted (because the
        ///     operation was already in  progress)
        ///  
        public bool Abort()
        { 
            bool removed = false; 

            if (_dispatcher != null) 
            {
                removed = _dispatcher.Abort(this);

                if (removed) 
                {
                    // Raise the Aborted so anyone who is waiting will wake up. 
                    EventHandler aborted = _aborted; 
                    if (aborted != null)
                    { 
                        aborted(this, EventArgs.Empty);
                    }
                }
            } 

            return removed; 
        } 

        ///  
        ///     Name of this operation.
        /// 
        /// 
        ///     Returns a string representation of the operation to be invoked. 
        /// 
        internal String Name 
        { 
            get
            { 
                return _method.Method.DeclaringType + "." + _method.Method.Name;
            }
        }
 
        /// 
        ///     Returns the result of the operation if it has completed. 
        ///  
        public object Result
        { 
            get
            {
                return _result;
            } 
        }
 
        ///  
        ///     An event that is raised when the operation is aborted.
        ///  
        public event EventHandler Aborted
        {
            add
            { 
                lock (DispatcherLock)
                { 
                    _aborted = (EventHandler) Delegate.Combine(_aborted, value); 
                }
            } 

            remove
            {
                lock(DispatcherLock) 
                {
                    _aborted = (EventHandler) Delegate.Remove(_aborted, value); 
                } 
            }
        } 

        /// 
        ///     An event that is raised when the operation completes.
        ///  
        public event EventHandler Completed
        { 
            add 
            {
                lock (DispatcherLock) 
                {
                    _completed = (EventHandler) Delegate.Combine(_completed, value);
                }
            } 

            remove 
            { 
                lock(DispatcherLock)
                { 
                    _completed = (EventHandler) Delegate.Remove(_completed, value);
                }
            }
        } 

        // Note: this is called by the Dispatcher to actually invoke the operation. 
        // Invoke --> InvokeInSecurityContext --> InvokeImpl 
        /// 
        ///    Critical: This code calls into ExecutionContext.Run which is link demand protected 
        ///              accesses _executionContext
        /// 
        [SecurityCritical]
        internal object Invoke() 
        {
            // Mark this operation as executing. 
            _status = DispatcherOperationStatus.Executing; 

            // Continue using the execution context that was active when the operation 
            // was begun.
            if(_executionContext != null)
            {
                ExecutionContext.Run(_executionContext, _invokeInSecurityContext, this); 
            }
            else 
            { 
                // _executionContext can be null if someone called
                // ExecutionContext.SupressFlow before calling BeginInvoke/Invoke. 
                // In this case we'll just call the invokation directly.
                // SupressFlow is a privileged operation, so this is not a
                // security hole.
                _invokeInSecurityContext(this); 
            }
 
            // This block of code needs to be synchronized with the constructor of 
            // DispatcherOperationEvent which may be called through
            // Dispatcher.Invoke on a separate thread. 

            EventHandler completed;
            lock(DispatcherLock)
            { 
                // Mark this operation as completed.
                _status = DispatcherOperationStatus.Completed; 
 
                // Read the Completed event handler.
                completed = _completed; 
            }

            // Raise the Completed so anyone who is waiting will wake up.
            if(completed != null) 
            {
                completed(this, EventArgs.Empty); 
            } 

            return _result; 
        }

        // Invoke --> InvokeInSecurityContext --> InvokeImpl
        ///  
        ///     Critical: This code can execute arbitrary code
        ///  
        [SecurityCritical] 
        private static void InvokeInSecurityContext(Object state)
        { 
            DispatcherOperation operation = (DispatcherOperation) state;
            operation.InvokeImpl();
        }
 
        // Invoke --> InvokeInSecurityContext --> InvokeImpl
        ///  
        ///     Critical: This code calls into SynchronizationContext.SetSynchronizationContext which link demands 
        /// 
        [SecurityCritical] 
        private void InvokeImpl()
        {
            SynchronizationContext oldSynchronizationContext = SynchronizationContext.Current;
 
            try
            { 
                // We are executing under the "foreign" execution context, but the 
                // SynchronizationContext must be for the correct dispatcher.
                SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(_dispatcher)); 

                // Invoke the delegate that does the work for this operation.
                _result = _dispatcher.WrappedInvoke(_method, _args, _isSingleParameter);
            } 
            finally
            { 
                SynchronizationContext.SetSynchronizationContext(oldSynchronizationContext); 
            }
        } 

        private class DispatcherOperationFrame : DispatcherFrame
        {
            // Note: we pass "exitWhenRequested=false" to the base 
            // DispatcherFrame construsctor because we do not want to exit
            // this frame if the dispatcher is shutting down. This is 
            // because we may need to invoke operations during the shutdown process. 
            public DispatcherOperationFrame(DispatcherOperation op, TimeSpan timeout) : base(false)
            { 
                _operation = op;

                // We will exit this frame once the operation is completed or aborted.
                _operation.Aborted += new EventHandler(OnCompletedOrAborted); 
                _operation.Completed += new EventHandler(OnCompletedOrAborted);
 
                // We will exit the frame if the operation is not completed within 
                // the requested timeout.
                if(timeout.TotalMilliseconds > 0) 
                {
                    _waitTimer = new Timer(new TimerCallback(OnTimeout),
                                           null,
                                           timeout, 
                                           TimeSpan.FromMilliseconds(-1));
                } 
 
                // Some other thread could have aborted the operation while we were
                // setting up the handlers.  We check the state again and mark the 
                // frame as "should not continue" if this happened.
                if(_operation._status != DispatcherOperationStatus.Pending)
                {
                    Exit(); 
                }
 
            } 

            private void OnCompletedOrAborted(object sender, EventArgs e) 
            {
                Exit();
            }
 
            private void OnTimeout(object arg)
            { 
                Exit(); 
            }
 
            private void Exit()
            {
                Continue = false;
 
                if(_waitTimer != null)
                { 
                    _waitTimer.Dispose(); 
                }
 
                _operation.Aborted -= new EventHandler(OnCompletedOrAborted);
                _operation.Completed -= new EventHandler(OnCompletedOrAborted);
            }
 
            private DispatcherOperation _operation;
            private Timer _waitTimer; 
        } 

        private class DispatcherOperationEvent 
        {
            public DispatcherOperationEvent(DispatcherOperation op, TimeSpan timeout)
            {
                _operation = op; 
                _timeout = timeout;
                _event = new ManualResetEvent(false); 
                _eventClosed = false; 

                lock(DispatcherLock) 
                {
                    // We will set our event once the operation is completed or aborted.
                    _operation.Aborted += new EventHandler(OnCompletedOrAborted);
                    _operation.Completed += new EventHandler(OnCompletedOrAborted); 

                    // Since some other thread is dispatching this operation, it could 
                    // have been dispatched while we were setting up the handlers. 
                    // We check the state again and set the event ourselves if this
                    // happened. 
                    if(_operation._status != DispatcherOperationStatus.Pending && _operation._status != DispatcherOperationStatus.Executing)
                    {
                        _event.Set();
                    } 
                }
            } 
 
            private void OnCompletedOrAborted(object sender, EventArgs e)
            { 
                lock(DispatcherLock)
                {
                    if(!_eventClosed)
                    { 
                        _event.Set();
                    } 
                } 
            }
 
            public void WaitOne()
            {
                _event.WaitOne(_timeout, false);
 
                lock(DispatcherLock)
                { 
                    if(!_eventClosed) 
                    {
                        // Cleanup the events. 
                        _operation.Aborted -= new EventHandler(OnCompletedOrAborted);
                        _operation.Completed -= new EventHandler(OnCompletedOrAborted);

                        // Close the event immediately instead of waiting for a GC 
                        // because the Dispatcher is a a high-activity component and
                        // we could run out of events. 
                        _event.Close(); 

                        _eventClosed = true; 
                    }
                }
            }
 
            private object DispatcherLock
            { 
                get { return _operation.DispatcherLock; } 
            }
 
            private DispatcherOperation _operation;
            private TimeSpan _timeout;
            private ManualResetEvent _event;
            private bool _eventClosed; 
        }
 
        private object DispatcherLock 
        {
            get { return _dispatcher._instanceLock; } 
        }

        /// 
        ///     Obtained under an elevation. 
        /// 
        [SecurityCritical] 
        private ExecutionContext _executionContext; 
        private static ContextCallback _invokeInSecurityContext;
 
        private Dispatcher _dispatcher;
        private DispatcherPriority _priority; // NOTE: should be Priority
        private Delegate _method;
        private object _args; 

        private bool _isSingleParameter; 
 
        internal DispatcherOperationStatus _status; // set from Dispatcher
        private object _result; 

        internal PriorityItem _item; // The Dispatcher sets this when it enques/deques the item.

        EventHandler _aborted; 
        EventHandler _completed;
    } 
 
    /// 
    ///     A convenient delegate to use for dispatcher operations. 
    /// 
    public delegate object DispatcherOperationCallback(object arg);
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK