From 134f86e8d5c414409631b25b8c6f0ee45fbd8631 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Thu, 3 Nov 2016 21:44:39 +1000 Subject: Initial update to OpenSim 0.8.2.1 source code. --- ThirdParty/SmartThreadPool/WorkItem.cs | 659 ++++++++++++++++----------------- 1 file changed, 313 insertions(+), 346 deletions(-) (limited to 'ThirdParty/SmartThreadPool/WorkItem.cs') diff --git a/ThirdParty/SmartThreadPool/WorkItem.cs b/ThirdParty/SmartThreadPool/WorkItem.cs index d0c0524..185f10c 100644 --- a/ThirdParty/SmartThreadPool/WorkItem.cs +++ b/ThirdParty/SmartThreadPool/WorkItem.cs @@ -1,58 +1,13 @@ -// Ami Bar -// amibar@gmail.com - using System; using System.Threading; using System.Diagnostics; namespace Amib.Threading.Internal { - #region WorkItem Delegate - - /// - /// An internal delegate to call when the WorkItem starts or completes - /// - internal delegate void WorkItemStateCallback(WorkItem workItem); - - #endregion - - #region IInternalWorkItemResult interface - - public class CanceledWorkItemsGroup - { - public readonly static CanceledWorkItemsGroup NotCanceledWorkItemsGroup = new CanceledWorkItemsGroup(); - - private bool _isCanceled = false; - public bool IsCanceled - { - get { return _isCanceled; } - set { _isCanceled = value; } - } - } - - internal interface IInternalWorkItemResult - { - event WorkItemStateCallback OnWorkItemStarted; - event WorkItemStateCallback OnWorkItemCompleted; - } - - #endregion - - #region IWorkItem interface - - public interface IWorkItem - { - - } - - #endregion - - #region WorkItem class - /// /// Holds a callback delegate and the state for that delegate. /// - public class WorkItem : IHasWorkItemPriority, IWorkItem + public partial class WorkItem : IHasWorkItemPriority { #region WorkItemState enum @@ -61,33 +16,57 @@ namespace Amib.Threading.Internal /// private enum WorkItemState { - InQueue, - InProgress, - Completed, - Canceled, + InQueue = 0, // Nexts: InProgress, Canceled + InProgress = 1, // Nexts: Completed, Canceled + Completed = 2, // Stays Completed + Canceled = 3, // Stays Canceled } - #endregion + private static bool IsValidStatesTransition(WorkItemState currentState, WorkItemState nextState) + { + bool valid = false; + + switch (currentState) + { + case WorkItemState.InQueue: + valid = (WorkItemState.InProgress == nextState) || (WorkItemState.Canceled == nextState); + break; + case WorkItemState.InProgress: + valid = (WorkItemState.Completed == nextState) || (WorkItemState.Canceled == nextState); + break; + case WorkItemState.Completed: + case WorkItemState.Canceled: + // Cannot be changed + break; + default: + // Unknown state + Debug.Assert(false); + break; + } - #region Member Variables + return valid; + } - public Thread currentThread; + #endregion + + #region Fields /// /// Callback delegate for the callback. /// - private WorkItemCallback _callback; + private readonly WorkItemCallback _callback; /// /// State with which to call the callback delegate. /// private object _state; +#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE) /// /// Stores the caller's context /// - private CallerThreadContext _callerContext; - + private readonly CallerThreadContext _callerContext; +#endif /// /// Holds the result of the mehtod /// @@ -117,12 +96,12 @@ namespace Amib.Threading.Internal /// /// Represents the result state of the work item /// - private WorkItemResult _workItemResult; + private readonly WorkItemResult _workItemResult; /// /// Work item info /// - private WorkItemInfo _workItemInfo; + private readonly WorkItemInfo _workItemInfo; /// /// Called when the WorkItem starts @@ -141,30 +120,41 @@ namespace Amib.Threading.Internal private CanceledWorkItemsGroup _canceledWorkItemsGroup = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup; /// + /// A reference to an object that indicates whatever the + /// SmartThreadPool has been canceled + /// + private CanceledWorkItemsGroup _canceledSmartThreadPool = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup; + + /// /// The work item group this work item belong to. - /// /// - private IWorkItemsGroup _workItemsGroup; + private readonly IWorkItemsGroup _workItemsGroup; - #region Performance Counter fields + /// + /// The thread that executes this workitem. + /// This field is available for the period when the work item is executed, before and after it is null. + /// + private Thread _executingThread; /// - /// The time when the work items is queued. - /// Used with the performance counter. + /// The absulote time when the work item will be timeout /// - private DateTime _queuedTime; + private long _expirationTime; + + #region Performance Counter fields + + + /// - /// The time when the work items starts its execution. - /// Used with the performance counter. + /// Stores how long the work item waited on the stp queue /// - private DateTime _beginProcessTime; + private Stopwatch _waitingOnQueueStopwatch; /// - /// The time when the work items ends its execution. - /// Used with the performance counter. + /// Stores how much time it took the work item to execute after it went out of the queue /// - private DateTime _endProcessTime; + private Stopwatch _processingStopwatch; #endregion @@ -174,17 +164,25 @@ namespace Amib.Threading.Internal public TimeSpan WaitingTime { - get + get { - return (_beginProcessTime - _queuedTime); + return _waitingOnQueueStopwatch.Elapsed; } } public TimeSpan ProcessTime { - get + get + { + return _processingStopwatch.Elapsed; + } + } + + internal WorkItemInfo WorkItemInfo + { + get { - return (_endProcessTime - _beginProcessTime); + return _workItemInfo; } } @@ -195,6 +193,8 @@ namespace Amib.Threading.Internal /// /// Initialize the callback holding object. /// + /// The workItemGroup of the workitem + /// The WorkItemInfo of te workitem /// Callback delegate for the callback. /// State with which to call the callback delegate. /// @@ -203,16 +203,18 @@ namespace Amib.Threading.Internal public WorkItem( IWorkItemsGroup workItemsGroup, WorkItemInfo workItemInfo, - WorkItemCallback callback, + WorkItemCallback callback, object state) { _workItemsGroup = workItemsGroup; _workItemInfo = workItemInfo; +#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE) if (_workItemInfo.UseCallerCallContext || _workItemInfo.UseCallerHttpContext) { _callerContext = CallerThreadContext.Capture(_workItemInfo.UseCallerCallContext, _workItemInfo.UseCallerHttpContext); } +#endif _callback = callback; _state = state; @@ -222,9 +224,18 @@ namespace Amib.Threading.Internal internal void Initialize() { + // The _workItemState is changed directly instead of using the SetWorkItemState + // method since we don't want to go throught IsValidStateTransition. _workItemState = WorkItemState.InQueue; + _workItemCompleted = null; _workItemCompletedRefCount = 0; + _waitingOnQueueStopwatch = new Stopwatch(); + _processingStopwatch = new Stopwatch(); + _expirationTime = + _workItemInfo.Timeout > 0 ? + DateTime.UtcNow.Ticks + _workItemInfo.Timeout * TimeSpan.TicksPerMillisecond : + long.MaxValue; } internal bool WasQueuedBy(IWorkItemsGroup workItemsGroup) @@ -237,17 +248,16 @@ namespace Amib.Threading.Internal #region Methods - public CanceledWorkItemsGroup CanceledWorkItemsGroup + internal CanceledWorkItemsGroup CanceledWorkItemsGroup { - get - { - return _canceledWorkItemsGroup; - } + get { return _canceledWorkItemsGroup; } + set { _canceledWorkItemsGroup = value; } + } - set - { - _canceledWorkItemsGroup = value; - } + internal CanceledWorkItemsGroup CanceledSmartThreadPool + { + get { return _canceledSmartThreadPool; } + set { _canceledSmartThreadPool = value; } } /// @@ -259,9 +269,10 @@ namespace Amib.Threading.Internal /// public bool StartingWorkItem() { - _beginProcessTime = DateTime.Now; + _waitingOnQueueStopwatch.Stop(); + _processingStopwatch.Start(); - lock(this) + lock (this) { if (IsCanceled) { @@ -277,6 +288,9 @@ namespace Amib.Threading.Internal Debug.Assert(WorkItemState.InQueue == GetWorkItemState()); + // No need for a lock yet, only after the state has changed to InProgress + _executingThread = Thread.CurrentThread; + SetWorkItemState(WorkItemState.InProgress); } @@ -291,7 +305,7 @@ namespace Amib.Threading.Internal CallToPostExecute currentCallToPostExecute = 0; // Execute the work item if we are in the correct state - switch(GetWorkItemState()) + switch (GetWorkItemState()) { case WorkItemState.InProgress: currentCallToPostExecute |= CallToPostExecute.WhenWorkItemNotCanceled; @@ -311,7 +325,7 @@ namespace Amib.Threading.Internal PostExecute(); } - _endProcessTime = DateTime.Now; + _processingStopwatch.Stop(); } internal void FireWorkItemCompleted() @@ -323,8 +337,21 @@ namespace Amib.Threading.Internal _workItemCompletedEvent(this); } } - catch // Ignore exceptions - {} + catch // Suppress exceptions + { } + } + + internal void FireWorkItemStarted() + { + try + { + if (null != _workItemStartedEvent) + { + _workItemStartedEvent(this); + } + } + catch // Suppress exceptions + { } } /// @@ -332,32 +359,70 @@ namespace Amib.Threading.Internal /// private void ExecuteWorkItem() { + +#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE) CallerThreadContext ctc = null; if (null != _callerContext) { ctc = CallerThreadContext.Capture(_callerContext.CapturedCallContext, _callerContext.CapturedHttpContext); CallerThreadContext.Apply(_callerContext); } +#endif Exception exception = null; object result = null; try { - result = _callback(_state); + try + { + result = _callback(_state); + } + catch (Exception e) + { + // Save the exception so we can rethrow it later + exception = e; + } + + // Remove the value of the execution thread, so it will be impossible to cancel the work item, + // since it is already completed. + // Cancelling a work item that already completed may cause the abortion of the next work item!!! + Thread executionThread = Interlocked.CompareExchange(ref _executingThread, null, _executingThread); + + if (null == executionThread) + { + // Oops! we are going to be aborted..., Wait here so we can catch the ThreadAbortException + Thread.Sleep(60 * 1000); + + // If after 1 minute this thread was not aborted then let it continue working. + } } - catch (Exception e) + // We must treat the ThreadAbortException or else it will be stored in the exception variable + catch (ThreadAbortException tae) { - // Save the exception so we can rethrow it later - exception = e; + tae.GetHashCode(); + // Check if the work item was cancelled + // If we got a ThreadAbortException and the STP is not shutting down, it means the + // work items was cancelled. + if (!SmartThreadPool.CurrentThreadEntry.AssociatedSmartThreadPool.IsShuttingdown) + { +#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE) + Thread.ResetAbort(); +#endif + } } - + +#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE) if (null != _callerContext) { CallerThreadContext.Apply(ctc); } +#endif - SetResult(result, exception); + if (!SmartThreadPool.IsWorkItemCanceled) + { + SetResult(result, exception); + } } /// @@ -369,9 +434,9 @@ namespace Amib.Threading.Internal { try { - _workItemInfo.PostExecuteWorkItemCallback(this._workItemResult); + _workItemInfo.PostExecuteWorkItemCallback(_workItemResult); } - catch (Exception e) + catch (Exception e) { Debug.Assert(null != e); } @@ -382,6 +447,8 @@ namespace Amib.Threading.Internal /// Set the result of the work item to return /// /// The result of the work item + /// The exception that was throw while the workitem executed, null + /// if there was no exception. internal void SetResult(object result, Exception exception) { _result = result; @@ -401,48 +468,48 @@ namespace Amib.Threading.Internal /// /// Wait for all work items to complete /// - /// Array of work item result objects + /// Array of work item result objects /// The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. /// /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. /// /// A cancel wait handle to interrupt the wait if needed /// - /// true when every work item in workItemResults has completed; otherwise false. + /// true when every work item in waitableResults has completed; otherwise false. /// internal static bool WaitAll( - IWorkItemResult [] workItemResults, + IWaitableResult[] waitableResults, int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle) { - if (0 == workItemResults.Length) + if (0 == waitableResults.Length) { return true; } bool success; - WaitHandle [] waitHandles = new WaitHandle[workItemResults.Length];; - GetWaitHandles(workItemResults, waitHandles); + WaitHandle[] waitHandles = new WaitHandle[waitableResults.Length]; + GetWaitHandles(waitableResults, waitHandles); if ((null == cancelWaitHandle) && (waitHandles.Length <= 64)) { - success = WaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext); + success = STPEventWaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext); } else { success = true; int millisecondsLeft = millisecondsTimeout; - DateTime start = DateTime.Now; + Stopwatch stopwatch = Stopwatch.StartNew(); - WaitHandle [] whs; + WaitHandle[] whs; if (null != cancelWaitHandle) { - whs = new WaitHandle [] { null, cancelWaitHandle }; + whs = new WaitHandle[] { null, cancelWaitHandle }; } else { - whs = new WaitHandle [] { null }; + whs = new WaitHandle[] { null }; } bool waitInfinitely = (Timeout.Infinite == millisecondsTimeout); @@ -450,7 +517,7 @@ namespace Amib.Threading.Internal // We cannot use WaitHandle.WaitAll directly, because the cancelWaitHandle // won't affect it. // Each iteration we update the time left for the timeout. - for(int i = 0; i < workItemResults.Length; ++i) + for (int i = 0; i < waitableResults.Length; ++i) { // WaitAny don't work with negative numbers if (!waitInfinitely && (millisecondsLeft < 0)) @@ -460,23 +527,22 @@ namespace Amib.Threading.Internal } whs[0] = waitHandles[i]; - int result = WaitHandle.WaitAny(whs, millisecondsLeft, exitContext); - if((result > 0) || (WaitHandle.WaitTimeout == result)) + int result = STPEventWaitHandle.WaitAny(whs, millisecondsLeft, exitContext); + if ((result > 0) || (STPEventWaitHandle.WaitTimeout == result)) { success = false; break; } - if(!waitInfinitely) + if (!waitInfinitely) { // Update the time left to wait - TimeSpan ts = DateTime.Now - start; - millisecondsLeft = millisecondsTimeout - (int)ts.TotalMilliseconds; + millisecondsLeft = millisecondsTimeout - (int)stopwatch.ElapsedMilliseconds; } } } // Release the wait handles - ReleaseWaitHandles(workItemResults); + ReleaseWaitHandles(waitableResults); return success; } @@ -484,7 +550,7 @@ namespace Amib.Threading.Internal /// /// Waits for any of the work items in the specified array to complete, cancel, or timeout /// - /// Array of work item result objects + /// Array of work item result objects /// The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely. /// /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. @@ -493,38 +559,38 @@ namespace Amib.Threading.Internal /// /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled. /// - internal static int WaitAny( - IWorkItemResult [] workItemResults, + internal static int WaitAny( + IWaitableResult[] waitableResults, int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle) { - WaitHandle [] waitHandles = null; + WaitHandle[] waitHandles; if (null != cancelWaitHandle) { - waitHandles = new WaitHandle[workItemResults.Length+1]; - GetWaitHandles(workItemResults, waitHandles); - waitHandles[workItemResults.Length] = cancelWaitHandle; + waitHandles = new WaitHandle[waitableResults.Length + 1]; + GetWaitHandles(waitableResults, waitHandles); + waitHandles[waitableResults.Length] = cancelWaitHandle; } else { - waitHandles = new WaitHandle[workItemResults.Length]; - GetWaitHandles(workItemResults, waitHandles); + waitHandles = new WaitHandle[waitableResults.Length]; + GetWaitHandles(waitableResults, waitHandles); } - int result = WaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext); + int result = STPEventWaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext); // Treat cancel as timeout if (null != cancelWaitHandle) { - if (result == workItemResults.Length) + if (result == waitableResults.Length) { - result = WaitHandle.WaitTimeout; + result = STPEventWaitHandle.WaitTimeout; } } - ReleaseWaitHandles(workItemResults); + ReleaseWaitHandles(waitableResults); return result; } @@ -532,16 +598,16 @@ namespace Amib.Threading.Internal /// /// Fill an array of wait handles with the work items wait handles. /// - /// An array of work item results + /// An array of work item results /// An array of wait handles to fill private static void GetWaitHandles( - IWorkItemResult [] workItemResults, - WaitHandle [] waitHandles) + IWaitableResult[] waitableResults, + WaitHandle[] waitHandles) { - for(int i = 0; i < workItemResults.Length; ++i) + for (int i = 0; i < waitableResults.Length; ++i) { - WorkItemResult wir = workItemResults[i] as WorkItemResult; - Debug.Assert(null != wir, "All workItemResults must be WorkItemResult objects"); + WorkItemResult wir = waitableResults[i].GetWorkItemResult() as WorkItemResult; + Debug.Assert(null != wir, "All waitableResults must be WorkItemResult objects"); waitHandles[i] = wir.GetWorkItem().GetWaitHandle(); } @@ -550,40 +616,64 @@ namespace Amib.Threading.Internal /// /// Release the work items' wait handles /// - /// An array of work item results - private static void ReleaseWaitHandles(IWorkItemResult [] workItemResults) + /// An array of work item results + private static void ReleaseWaitHandles(IWaitableResult[] waitableResults) { - for(int i = 0; i < workItemResults.Length; ++i) + for (int i = 0; i < waitableResults.Length; ++i) { - WorkItemResult wir = workItemResults[i] as WorkItemResult; + WorkItemResult wir = (WorkItemResult)waitableResults[i].GetWorkItemResult(); wir.GetWorkItem().ReleaseWaitHandle(); } } - #endregion - + #region Private Members private WorkItemState GetWorkItemState() { - if (_canceledWorkItemsGroup.IsCanceled) + lock (this) { - return WorkItemState.Canceled; - } - return _workItemState; + if (WorkItemState.Completed == _workItemState) + { + return _workItemState; + } + + long nowTicks = DateTime.UtcNow.Ticks; + if (WorkItemState.Canceled != _workItemState && nowTicks > _expirationTime) + { + _workItemState = WorkItemState.Canceled; + } + + if (WorkItemState.InProgress == _workItemState) + { + return _workItemState; + } + + if (CanceledSmartThreadPool.IsCanceled || CanceledWorkItemsGroup.IsCanceled) + { + return WorkItemState.Canceled; + } + + return _workItemState; + } } + + /// /// Sets the work item's state /// /// The state to set the work item to private void SetWorkItemState(WorkItemState workItemState) { - lock(this) + lock (this) { - _workItemState = workItemState; + if (IsValidStatesTransition(_workItemState, workItemState)) + { + _workItemState = workItemState; + } } } @@ -594,7 +684,7 @@ namespace Amib.Threading.Internal private void SignalComplete(bool canceled) { SetWorkItemState(canceled ? WorkItemState.Canceled : WorkItemState.Completed); - lock(this) + lock (this) { // If someone is waiting then signal. if (null != _workItemCompleted) @@ -606,40 +696,93 @@ namespace Amib.Threading.Internal internal void WorkItemIsQueued() { - _queuedTime = DateTime.Now; + _waitingOnQueueStopwatch.Start(); } #endregion - + #region Members exposed by WorkItemResult /// /// Cancel the work item if it didn't start running yet. /// /// Returns true on success or false if the work item is in progress or already completed - private bool Cancel() + private bool Cancel(bool abortExecution) { - lock(this) +#if (_WINDOWS_CE) + if(abortExecution) + { + throw new ArgumentOutOfRangeException("abortExecution", "WindowsCE doesn't support this feature"); + } +#endif + bool success = false; + bool signalComplete = false; + + lock (this) { - switch(GetWorkItemState()) + switch (GetWorkItemState()) { case WorkItemState.Canceled: //Debug.WriteLine("Work item already canceled"); - return true; + if (abortExecution) + { + Thread executionThread = Interlocked.CompareExchange(ref _executingThread, null, _executingThread); + if (null != executionThread) + { + executionThread.Abort(); // "Cancel" + // No need to signalComplete, because we already cancelled this work item + // so it already signaled its completion. + //signalComplete = true; + } + } + success = true; + break; case WorkItemState.Completed: - case WorkItemState.InProgress: //Debug.WriteLine("Work item cannot be canceled"); - return false; + break; + case WorkItemState.InProgress: + if (abortExecution) + { + Thread executionThread = Interlocked.CompareExchange(ref _executingThread, null, _executingThread); + if (null != executionThread) + { + executionThread.Abort(); // "Cancel" + success = true; + signalComplete = true; + } + } + else + { + // ************************** + // Stock SmartThreadPool 2.2.3 sets these to true and relies on the thread to check the + // WorkItem cancellation status. However, OpenSimulator uses a different mechanism to notify + // scripts of co-operative termination and the abort code also relies on this method + // returning false in order to implement a small wait. + // + // Therefore, as was the case previously with STP, we will not signal successful cancellation + // here. It's possible that OpenSimulator code could be changed in the future to remove + // the need for this change. + // ************************** + success = false; + signalComplete = false; + } + break; case WorkItemState.InQueue: // Signal to the wait for completion that the work // item has been completed (canceled). There is no // reason to wait for it to get out of the queue - SignalComplete(true); + signalComplete = true; //Debug.WriteLine("Work item canceled"); - return true; + success = true; + break; + } + + if (signalComplete) + { + SignalComplete(true); } } - return false; + return success; } /// @@ -653,7 +796,7 @@ namespace Amib.Threading.Internal bool exitContext, WaitHandle cancelWaitHandle) { - Exception e = null; + Exception e; object result = GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e); if (null != e) { @@ -694,7 +837,7 @@ namespace Amib.Threading.Internal { WaitHandle wh = GetWaitHandle(); - bool timeout = !wh.WaitOne(millisecondsTimeout, exitContext); + bool timeout = !STPEventWaitHandle.WaitOne(wh, millisecondsTimeout, exitContext); ReleaseWaitHandle(); @@ -706,10 +849,10 @@ namespace Amib.Threading.Internal else { WaitHandle wh = GetWaitHandle(); - int result = WaitHandle.WaitAny(new WaitHandle[] { wh, cancelWaitHandle }); + int result = STPEventWaitHandle.WaitAny(new WaitHandle[] { wh, cancelWaitHandle }); ReleaseWaitHandle(); - switch(result) + switch (result) { case 0: // The work item signaled @@ -717,7 +860,7 @@ namespace Amib.Threading.Internal // work item (not the get result) break; case 1: - case WaitHandle.WaitTimeout: + case STPEventWaitHandle.WaitTimeout: throw new WorkItemTimeoutException("Work item timeout"); default: Debug.Assert(false); @@ -745,11 +888,11 @@ namespace Amib.Threading.Internal /// private WaitHandle GetWaitHandle() { - lock(this) + lock (this) { if (null == _workItemCompleted) { - _workItemCompleted = new ManualResetEvent(IsCompleted); + _workItemCompleted = EventWaitHandleFactory.CreateManualResetEvent(IsCompleted); } ++_workItemCompletedRefCount; } @@ -758,7 +901,7 @@ namespace Amib.Threading.Internal private void ReleaseWaitHandle() { - lock(this) + lock (this) { if (null != _workItemCompleted) { @@ -779,10 +922,10 @@ namespace Amib.Threading.Internal { get { - lock(this) + lock (this) { WorkItemState workItemState = GetWorkItemState(); - return ((workItemState == WorkItemState.Completed) || + return ((workItemState == WorkItemState.Completed) || (workItemState == WorkItemState.Canceled)); } } @@ -795,7 +938,7 @@ namespace Amib.Threading.Internal { get { - lock(this) + lock (this) { return (GetWorkItemState() == WorkItemState.Canceled); } @@ -843,172 +986,6 @@ namespace Amib.Threading.Internal } } - - #region WorkItemResult class - - private class WorkItemResult : IWorkItemResult, IInternalWorkItemResult - { - /// - /// A back reference to the work item - /// - private WorkItem _workItem; - - public WorkItemResult(WorkItem workItem) - { - _workItem = workItem; - } - - internal WorkItem GetWorkItem() - { - return _workItem; - } - - #region IWorkItemResult Members - - public bool IsCompleted - { - get - { - return _workItem.IsCompleted; - } - } - - public void Abort() - { - _workItem.Abort(); - } - - public bool IsCanceled - { - get - { - return _workItem.IsCanceled; - } - } - - public object GetResult() - { - return _workItem.GetResult(Timeout.Infinite, true, null); - } - - public object GetResult(int millisecondsTimeout, bool exitContext) - { - return _workItem.GetResult(millisecondsTimeout, exitContext, null); - } - - public object GetResult(TimeSpan timeout, bool exitContext) - { - return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, null); - } - - public object GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle) - { - return _workItem.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle); - } - - public object GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle) - { - return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle); - } - - public object GetResult(out Exception e) - { - return _workItem.GetResult(Timeout.Infinite, true, null, out e); - } - - public object GetResult(int millisecondsTimeout, bool exitContext, out Exception e) - { - return _workItem.GetResult(millisecondsTimeout, exitContext, null, out e); - } - - public object GetResult(TimeSpan timeout, bool exitContext, out Exception e) - { - return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, null, out e); - } - - public object GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e) - { - return _workItem.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e); - } - - public object GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e) - { - return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle, out e); - } - - public bool Cancel() - { - return _workItem.Cancel(); - } - - public object State - { - get - { - return _workItem._state; - } - } - - public WorkItemPriority WorkItemPriority - { - get - { - return _workItem._workItemInfo.WorkItemPriority; - } - } - - /// - /// Return the result, same as GetResult() - /// - public object Result - { - get { return GetResult(); } - } - - /// - /// Returns the exception if occured otherwise returns null. - /// This value is valid only after the work item completed, - /// before that it is always null. - /// - public object Exception - { - get { return _workItem._exception; } - } - - #endregion - - #region IInternalWorkItemResult Members - - public event WorkItemStateCallback OnWorkItemStarted - { - add - { - _workItem.OnWorkItemStarted += value; - } - remove - { - _workItem.OnWorkItemStarted -= value; - } - } - - - public event WorkItemStateCallback OnWorkItemCompleted - { - add - { - _workItem.OnWorkItemCompleted += value; - } - remove - { - _workItem.OnWorkItemCompleted -= value; - } - } - - #endregion - } - - #endregion - public void DisposeOfState() { if (_workItemInfo.DisposeOfStateObjects) @@ -1021,15 +998,5 @@ namespace Amib.Threading.Internal } } } - - public void Abort() - { - lock (this) - { - if(currentThread != null) - currentThread.Abort(); - } - } } - #endregion } -- cgit v1.1