/// <summary> /// Waits until the process started by calling BeginInvoke completes, and then returns /// the value generated by the process. /// </summary> /// <param name="result"> /// An IAsyncResult interface that represents the asynchronous operation started /// by calling BeginInvoke. /// </param> /// <returns> /// An Object that represents the return value generated by the asynchronous operation. /// </returns> /// <remarks> /// This method gets the return value of the asynchronous operation represented by the /// IAsyncResult passed by this interface. If the asynchronous operation has not completed, this method will wait until the result is available. /// </remarks> public object EndInvoke(IAsyncResult result) { #region Require if (disposed) { throw new ObjectDisposedException("DelegateQueue"); } else if (!(result is DelegateQueueAsyncResult)) { throw new ArgumentException(); } else if (((DelegateQueueAsyncResult)result).Owner != this) { throw new ArgumentException(); } #endregion result.AsyncWaitHandle.WaitOne(); DelegateQueueAsyncResult r = (DelegateQueueAsyncResult)result; if (r.Error != null) { throw r.Error; } return(r.ReturnValue); }
/// <summary> /// Dispatches an asynchronous message to this synchronization context. /// </summary> /// <param name="d"> /// The SendOrPostCallback delegate to call. /// </param> /// <param name="state"> /// The object passed to the delegate. /// </param> /// <remarks> /// The Post method starts an asynchronous request to post a message. /// </remarks> public void PostPriority(SendOrPostCallback d, object state) { #region Require if (disposed) { throw new ObjectDisposedException("DelegateQueue"); } else if (d == null) { throw new ArgumentNullException(); } #endregion lock (lockObject) { DelegateQueueAsyncResult result = new DelegateQueueAsyncResult(this, d, new object[] { state }, false, NotificationType.PostCompleted); // Put the method at the front of the queue. delegateDeque.PushFront(result); Monitor.Pulse(lockObject); } }
/// <summary> /// Executes the delegate on the main thread that this DelegateQueue executes on. /// </summary> /// <param name="method"> /// A Delegate that contains a method to call, in the context of the thread for the DelegateQueue. /// </param> /// <param name="args"> /// An array of type Object that represents the arguments to pass to the given method. /// </param> /// <returns> /// An Object that represents the return value from the delegate being invoked, or a /// null reference (Nothing in Visual Basic) if the delegate has no return value. /// </returns> /// <remarks> /// <para>Unlike BeginInvoke, this method operates synchronously, that is, it waits until /// the process completes before returning. Exceptions raised during the call are propagated /// back to the caller.</para> /// <para>Use this method when calling a method from a different thread to marshal the call /// to the proper thread.</para> /// </remarks> public object Invoke(Delegate method, params object[] args) { if (disposed) { throw new ObjectDisposedException("DelegateQueue"); } else if (method == null) { throw new ArgumentNullException(); } object returnValue = null; if (InvokeRequired) { DelegateQueueAsyncResult result = new DelegateQueueAsyncResult(this, method, args, false, NotificationType.None); lock (lockObject) { delegateDeque.Enqueue(result); Monitor.Pulse(lockObject); } returnValue = EndInvoke(result); } else { // Invoke the method here rather than placing it in the queue. returnValue = method.DynamicInvoke(args); } return(returnValue); }
/// <summary> /// Executes the delegate on the main thread that this DelegateQueue executes on. /// </summary> /// <param name="method"> /// A Delegate to a method that takes parameters of the same number and type that /// are contained in args. /// </param> /// <param name="args"> /// An array of type Object to pass as arguments to the given method. This can be /// a null reference (Nothing in Visual Basic) if no arguments are needed. /// </param> /// <returns> /// An IAsyncResult interface that represents the asynchronous operation started /// by calling this method. /// </returns> /// <remarks> /// <para>The delegate is called asynchronously, and this method returns immediately. /// You can call this method from any thread. If you need the return value from a process /// started with this method, call EndInvoke to get the value.</para> /// <para>If you need to call the delegate synchronously, use the Invoke method instead.</para> /// </remarks> public IAsyncResult BeginInvoke(Delegate method, params object[] args) { if (disposed) { throw new ObjectDisposedException("DelegateQueue"); } else if (method == null) { throw new ArgumentNullException(); } DelegateQueueAsyncResult result; if (InvokeRequired) { result = new DelegateQueueAsyncResult(this, method, args, false, NotificationType.BeginInvokeCompleted); lock (lockObject) { delegateDeque.Enqueue(result); Monitor.Pulse(lockObject); } } else { result = new DelegateQueueAsyncResult(this, method, args, false, NotificationType.None); result.Invoke(); } return(result); }
/// <summary> /// Executes the delegate on the main thread that this object executes on. /// </summary> /// <param name="method"> /// A Delegate to a method that takes parameters of the same number and /// type that are contained in args. /// </param> /// <param name="args"> /// An array of type Object to pass as arguments to the given method. /// </param> /// <returns> /// An IAsyncResult interface that represents the asynchronous operation /// started by calling this method. /// </returns> /// <remarks> /// The delegate is placed at the beginning of the queue. Its invocation /// takes priority over delegates already in the queue. /// </remarks> public IAsyncResult BeginInvokePriority(Delegate method, params object[] args) { #region Require if (disposed) { throw new ObjectDisposedException("DelegateQueue"); } else if (method == null) { throw new ArgumentNullException(); } #endregion DelegateQueueAsyncResult result; // If BeginInvokePriority was called from a different thread than the one // in which the DelegateQueue is running. if (InvokeRequired) { result = new DelegateQueueAsyncResult(this, method, args, false, NotificationType.BeginInvokeCompleted); lock (lockObject) { // Put the method at the front of the queue. delegateDeque.PushFront(result); Monitor.Pulse(lockObject); } } // Else BeginInvokePriority was called from the same thread in which the // DelegateQueue is running. else { result = new DelegateQueueAsyncResult(this, method, args, true, NotificationType.None); // The method is invoked here instead of placing it in the // queue. The reason for this is that if EndInvoke is called // from the same thread in which the DelegateQueue is running and // the method has not been invoked, deadlock will occur. result.Invoke(); } return(result); }
/// <summary> /// Executes the delegate on the main thread that this object executes on. /// </summary> /// <param name="method"> /// A Delegate to a method that takes parameters of the same number and /// type that are contained in args. /// </param> /// <param name="args"> /// An array of type Object to pass as arguments to the given method. /// </param> /// <returns> /// An IAsyncResult interface that represents the asynchronous operation /// started by calling this method. /// </returns> /// <remarks> /// <para> /// The delegate is placed at the beginning of the queue. Its invocation /// takes priority over delegates already in the queue. /// </para> /// <para> /// Unlike BeginInvoke, this method operates synchronously, that is, it /// waits until the process completes before returning. Exceptions raised /// during the call are propagated back to the caller. /// </para> /// </remarks> public object InvokePriority(Delegate method, params object[] args) { #region Require if (disposed) { throw new ObjectDisposedException("DelegateQueue"); } else if (method == null) { throw new ArgumentNullException(); } #endregion object returnValue = null; // If InvokePriority was called from a different thread than the one // in which the DelegateQueue is running. if (InvokeRequired) { DelegateQueueAsyncResult result = new DelegateQueueAsyncResult(this, method, args, false, NotificationType.None); lock (lockObject) { // Put the method at the back of the queue. delegateDeque.PushFront(result); Monitor.Pulse(lockObject); } // Wait for the result of the method invocation. returnValue = EndInvoke(result); } // Else InvokePriority was called from the same thread in which the // DelegateQueue is running. else { // Invoke the method here rather than placing it in the queue. returnValue = method.DynamicInvoke(args); } return(returnValue); }
// Processes and invokes delegates. private void DelegateProcedure() { lock (lockObject) { // Signal the constructor that the thread is now running. Monitor.Pulse(lockObject); } // Set this DelegateQueue as the SynchronizationContext for this thread. SynchronizationContext.SetSynchronizationContext(this); // Placeholder for DelegateQueueAsyncResult objects. DelegateQueueAsyncResult result = null; // While the DelegateQueue has not been disposed. while (true) { // Critical section. lock (lockObject) { // If the DelegateQueue has been disposed, break out of loop; we're done. if (disposed) { break; } // If there are delegates waiting to be invoked. if (delegateDeque.Count > 0) { result = delegateDeque.PopFront(); } // Else there are no delegates waiting to be invoked. else { // Wait for next delegate. Monitor.Wait(lockObject); // If the DelegateQueue has been disposed, break out of loop; we're done. if (disposed) { break; } Debug.Assert(delegateDeque.Count > 0); result = delegateDeque.PopFront(); } } Debug.Assert(result != null); // Invoke the delegate. result.Invoke(); if (result.NotificationType == NotificationType.BeginInvokeCompleted) { InvokeCompletedEventArgs e = new InvokeCompletedEventArgs( result.Method, result.GetArgs(), result.ReturnValue, result.Error); OnInvokeCompleted(e); } else if (result.NotificationType == NotificationType.PostCompleted) { object[] args = result.GetArgs(); Debug.Assert(args.Length == 1); Debug.Assert(result.Method is SendOrPostCallback); PostCompletedEventArgs e = new PostCompletedEventArgs( (SendOrPostCallback)result.Method, result.Error, args[0]); OnPostCompleted(e); } else { Debug.Assert(result.NotificationType == NotificationType.None); } } Debug.WriteLine(delegateThread.Name + " Finished"); }
/// <summary> /// Executes the delegate on the main thread that this DelegateQueue executes on. /// </summary> /// <param name="method"> /// A Delegate that contains a method to call, in the context of the thread for the DelegateQueue. /// </param> /// <param name="args"> /// An array of type Object that represents the arguments to pass to the given method. /// </param> /// <returns> /// An Object that represents the return value from the delegate being invoked, or a /// null reference (Nothing in Visual Basic) if the delegate has no return value. /// </returns> /// <remarks> /// <para>Unlike BeginInvoke, this method operates synchronously, that is, it waits until /// the process completes before returning. Exceptions raised during the call are propagated /// back to the caller.</para> /// <para>Use this method when calling a method from a different thread to marshal the call /// to the proper thread.</para> /// </remarks> public object Invoke(Delegate method, params object[] args) { #region Require if(disposed) { throw new ObjectDisposedException("DelegateQueue"); } else if(method == null) { throw new ArgumentNullException(); } #endregion object returnValue = null; if(InvokeRequired) { DelegateQueueAsyncResult result = new DelegateQueueAsyncResult(this, method, args, false, NotificationType.None); lock(lockObject) { delegateQueue.Enqueue(result); Monitor.Pulse(lockObject); } returnValue = EndInvoke(result); } else { // Invoke the method here rather than placing it in the queue. returnValue = method.DynamicInvoke(args); } return returnValue; }
/// <summary> /// Executes the delegate on the main thread that this DelegateQueue executes on. /// </summary> /// <param name="method"> /// A Delegate to a method that takes parameters of the same number and type that /// are contained in args. /// </param> /// <param name="args"> /// An array of type Object to pass as arguments to the given method. This can be /// a null reference (Nothing in Visual Basic) if no arguments are needed. /// </param> /// <returns> /// An IAsyncResult interface that represents the asynchronous operation started /// by calling this method. /// </returns> /// <remarks> /// <para>The delegate is called asynchronously, and this method returns immediately. /// You can call this method from any thread. If you need the return value from a process /// started with this method, call EndInvoke to get the value.</para> /// <para>If you need to call the delegate synchronously, use the Invoke method instead.</para> /// </remarks> public IAsyncResult BeginInvoke(Delegate method, params object[] args) { #region Require if(disposed) { throw new ObjectDisposedException("DelegateQueue"); } else if(method == null) { throw new ArgumentNullException(); } #endregion DelegateQueueAsyncResult result; if(InvokeRequired) { result = new DelegateQueueAsyncResult(this, method, args, false, NotificationType.BeginInvokeCompleted); lock(lockObject) { delegateQueue.Enqueue(result); Monitor.Pulse(lockObject); } } else { result = new DelegateQueueAsyncResult(this, method, args, false, NotificationType.None); result.Invoke(); } return result; }
/// <summary> /// Dispatches an asynchronous message to this synchronization context. /// </summary> /// <param name="d"> /// The SendOrPostCallback delegate to call. /// </param> /// <param name="state"> /// The object passed to the delegate. /// </param> /// <remarks> /// The Post method starts an asynchronous request to post a message. /// </remarks> public void PostPriority(SendOrPostCallback d, object state) { #region Require if(disposed) { throw new ObjectDisposedException("DelegateQueue"); } else if(d == null) { throw new ArgumentNullException(); } #endregion lock(lockObject) { DelegateQueueAsyncResult result = new DelegateQueueAsyncResult(this, d, new object[] { state }, false, NotificationType.PostCompleted); // Put the method at the front of the queue. delegateDeque.PushFront(result); Monitor.Pulse(lockObject); } }
/// <summary> /// Executes the delegate on the main thread that this object executes on. /// </summary> /// <param name="method"> /// A Delegate to a method that takes parameters of the same number and /// type that are contained in args. /// </param> /// <param name="args"> /// An array of type Object to pass as arguments to the given method. /// </param> /// <returns> /// An IAsyncResult interface that represents the asynchronous operation /// started by calling this method. /// </returns> /// <remarks> /// <para> /// The delegate is placed at the beginning of the queue. Its invocation /// takes priority over delegates already in the queue. /// </para> /// <para> /// Unlike BeginInvoke, this method operates synchronously, that is, it /// waits until the process completes before returning. Exceptions raised /// during the call are propagated back to the caller. /// </para> /// </remarks> public object InvokePriority(Delegate method, params object[] args) { #region Require if(disposed) { throw new ObjectDisposedException("DelegateQueue"); } else if(method == null) { throw new ArgumentNullException(); } #endregion object returnValue = null; // If InvokePriority was called from a different thread than the one // in which the DelegateQueue is running. if(InvokeRequired) { DelegateQueueAsyncResult result = new DelegateQueueAsyncResult(this, method, args, false, NotificationType.None); lock(lockObject) { // Put the method at the back of the queue. delegateDeque.PushFront(result); Monitor.Pulse(lockObject); } // Wait for the result of the method invocation. returnValue = EndInvoke(result); } // Else InvokePriority was called from the same thread in which the // DelegateQueue is running. else { // Invoke the method here rather than placing it in the queue. returnValue = method.DynamicInvoke(args); } return returnValue; }
/// <summary> /// Executes the delegate on the main thread that this object executes on. /// </summary> /// <param name="method"> /// A Delegate to a method that takes parameters of the same number and /// type that are contained in args. /// </param> /// <param name="args"> /// An array of type Object to pass as arguments to the given method. /// </param> /// <returns> /// An IAsyncResult interface that represents the asynchronous operation /// started by calling this method. /// </returns> /// <remarks> /// The delegate is placed at the beginning of the queue. Its invocation /// takes priority over delegates already in the queue. /// </remarks> public IAsyncResult BeginInvokePriority(Delegate method, params object[] args) { #region Require if(disposed) { throw new ObjectDisposedException("DelegateQueue"); } else if(method == null) { throw new ArgumentNullException(); } #endregion DelegateQueueAsyncResult result; // If BeginInvokePriority was called from a different thread than the one // in which the DelegateQueue is running. if(InvokeRequired) { result = new DelegateQueueAsyncResult(this, method, args, false, NotificationType.BeginInvokeCompleted); lock(lockObject) { // Put the method at the front of the queue. delegateDeque.PushFront(result); Monitor.Pulse(lockObject); } } // Else BeginInvokePriority was called from the same thread in which the // DelegateQueue is running. else { result = new DelegateQueueAsyncResult(this, method, args, true, NotificationType.None); // The method is invoked here instead of placing it in the // queue. The reason for this is that if EndInvoke is called // from the same thread in which the DelegateQueue is running and // the method has not been invoked, deadlock will occur. result.Invoke(); } return result; }