[Adapdev-commits] Adapdev/src/Adapdev/Threading DelegateAdapter.cs,1.4,1.5 ThreadPoolWait.cs,1.4,1.5
Status: Beta
Brought to you by:
intesar66
From: Sean M. <int...@us...> - 2005-11-16 07:19:59
|
Update of /cvsroot/adapdev/Adapdev/src/Adapdev/Threading In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4187/src/Adapdev/Threading Added Files: DelegateAdapter.cs ThreadPoolWait.cs Log Message: --- NEW FILE: DelegateAdapter.cs --- #region Original Copyright 2003 Richard Lowe /** Taken from the following blog: http://blogs.geekdojo.net/richard/archive/2003/12/19/492.aspx Usage: using System; using System.Collections; using System.Threading; using Timing; using DelegateAdapter; public class Program { // Create any method and a corresponding delegate: public delegate double WorkMethodHandler(double factor, string name); public static double WorkMethod(double factor, string name) { Console.WriteLine(name); return 3.14159 * factor; } public static void Main() { // Create the DelegateAdapter with the appropriate method and arguments: DelegateAdapter adapter = new DelegateAdapter(new WorkMethodHandler(WorkMethod), 3.123456789, "Richard"); // Automatically creates new ThreadStart and passes to the Thread constructor. // The adapter is implicitly convertible to a ThreadStart, which is why this works. Thread worker = new Thread(adapter); // change the arguments: adapter.Args = new object[] {9.14159d, "Roberto"}; // run it: worker.Start(); // wait to exit: worker.Join(); // get result: Console.WriteLine(adapter.ReturnValue); } } **/ #endregion #region Modified Copyright / License Information /* Copyright 2004 - 2005 Adapdev Technologies, LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ============================ Author Log ============================ III Full Name SMM Sean McCormack (Adapdev) ============================ Change Log ============================ III MMDDYY Change */ #endregion namespace DelegateAdapter { using System; using System.Threading; /// <summary> /// Uses DynamicInvoke to allow any method to be easily mapped to the ThreadStart, WaitCallback or TimerCallback. /// </summary> public class DelegateAdapter { private object[] _args; public object[] Args { get { return _args; } set { _args = value; } } private Delegate _target; private object _returnValue; /// <summary> /// The return value, if any of the last execution of this DelegateAdapter's target method. /// </summary> public object ReturnValue { get { return _returnValue; } } /// <summary> /// Creates an instance of DelegateAdapter given any delegate. /// </summary> /// <param name="target">The delegate that will be invoked when one of the output delegates is invoked.</param> public DelegateAdapter(Delegate target) : this(target, null) { } /// <summary> /// Creates an instance of DelegateAdapter given any delegate and it's parameters to pass. /// </summary> /// <param name="target">The delegate that will be invoked when one of the output delegates is invoked.</param> /// <param name="args">The arguments that will be passed to the target delegate.</param> public DelegateAdapter(Delegate target, params object[] args) { _target = target; _args = args; } /// <summary> /// Dynamically invokes the target delegate with the provided arguments. /// </summary> public void Execute() { _returnValue = _target.DynamicInvoke(_args); } /// <summary> /// Dynamically invokes the target delegate with the state object provided by the caller. *Note* ignores any Args passed to the DelegateAdapter. /// </summary> /// <param name="state"></param> public void Execute(object state) { if (state is object[]) _returnValue = _target.DynamicInvoke(state as object[]); else _returnValue = _target.DynamicInvoke(new object[] {state}); } /// <summary> /// Creates a new, unique ThreadStart delegate for use with the Thread class. /// </summary> /// <returns>The new ThreadStart delegate</returns> public ThreadStart CreateThreadStart() { return new ThreadStart(Execute); } /// <summary> /// Creates a new, unique WaitCallback delegate for use with the ThreadPool class. /// </summary> /// <returns>The new WaitCallback delegate</returns> public WaitCallback CreateWaitCallback() { return new WaitCallback(Execute); } /// <summary> /// Creates a new, unique TimerCallback delegate for use with the Timer class. /// </summary> /// <returns>The new TimerCallback delegate</returns> public TimerCallback CreateTimerCallback() { return new TimerCallback(Execute); } public static implicit operator ThreadStart(DelegateAdapter adapter) { return adapter.CreateThreadStart(); } public static implicit operator WaitCallback(DelegateAdapter adapter) { return adapter.CreateWaitCallback(); } public static implicit operator TimerCallback(DelegateAdapter adapter) { return adapter.CreateTimerCallback(); } } } --- NEW FILE: ThreadPoolWait.cs --- // Stephen Toub // st...@mi... // http://msdn.microsoft.com/msdnmag/issues/04/10/NETMatters/ using System; using System.Threading; using System.Collections; namespace Adapdev.Threading { /// <summary>ThreadPool utility class that allows for easily waiting on queued delegates.</summary> public class ThreadPoolWait : IDisposable { /// <summary>Number of items remaining to be executed.</summary> private int _remainingWorkItems = 1; /// <summary>Event that signals whether all items have been executed.</summary> private ManualResetEvent _done = new ManualResetEvent(false); /// <summary>Queues a user work item to the ThreadPool.</summary> /// <param name="callback">The work item to be queued.</param> public void QueueUserWorkItem(WaitCallback callback) { QueueUserWorkItem(callback, null); } /// <summary>Queues a user work item to the ThreadPool.</summary> /// <param name="callback">The work item to be queued.</param> /// <param name="state">State to be passed to the queued work item</param> public void QueueUserWorkItem(WaitCallback callback, object state) { ThrowIfDisposed(); QueuedCallback qc = new QueuedCallback(); qc.Callback = callback; qc.State = state; Interlocked.Increment(ref _remainingWorkItems); ThreadPool.QueueUserWorkItem(new WaitCallback(HandleWorkItem), qc); } /// <summary>Wait for all items to finish executing.</summary> public bool WaitOne() { return WaitOne(-1, false); } /// <summary>Wait for all items to finish executing.</summary> public bool WaitOne(TimeSpan timeout, bool exitContext) { return WaitOne((int)timeout.TotalMilliseconds, exitContext); } /// <summary>Wait for all items to finish executing.</summary> public bool WaitOne(int millisecondsTimeout, bool exitContext) { ThrowIfDisposed(); DoneWorkItem(); bool rv = _done.WaitOne(millisecondsTimeout, exitContext); // If the event is set, then we'll return true, but first // reset so that this instance can be used again. If the // event isn't set, put back the 1 unit removed by calling // DoneWorkItem. The next time WaitOne is called, // this unit will be removed by the call to DoneWorkItem. if (rv) { _remainingWorkItems = 1; _done.Reset(); } else Interlocked.Increment(ref _remainingWorkItems); return rv; } /// <summary>Executes the callback passed as state and signals its completion when it has finished executing.</summary> /// <param name="state"></param> private void HandleWorkItem(object state) { QueuedCallback qc = (QueuedCallback)state; try { qc.Callback(qc.State); } finally { DoneWorkItem(); } } /// <summary>Decrements the number of remaining items, signaling the ManualResetEvent if 0 are left.</summary> private void DoneWorkItem() { if (Interlocked.Decrement(ref _remainingWorkItems) == 0) _done.Set(); } /// <summary>State class that wraps a WaitCallback and the state object to be passed to it.</summary> private class QueuedCallback { /// <summary>A callback delegate queued to the ThreadPool.</summary> public WaitCallback Callback; /// <summary>The state to be passed to the callback.</summary> public object State; } /// <summary>Throws an exception if this instance has already been disposed.</summary> private void ThrowIfDisposed() { if (_done == null) throw new ObjectDisposedException(GetType().Name); } /// <summary>Disposes this ThreadPoolWait.</summary> public void Dispose() { if (_done != null) { ((IDisposable)_done).Dispose(); _done = null; } } } } |