diff --git a/STPTests/TestCancel.cs b/STPTests/TestCancel.cs
index 51420f9..e2b32ed 100644
--- a/STPTests/TestCancel.cs
+++ b/STPTests/TestCancel.cs
@@ -77,6 +77,47 @@ namespace SmartThreadPoolTests
}
}
+ ///
+ /// 1. Create STP
+ /// 2. Queue work item that takes some time
+ /// 3. Wait for it to start
+ /// 4. Cancel the work item (soft)
+ /// 5. Work item's GetResult should throw WorkItemCancelException
+ ///
+ [Test]
+ [ExpectedException(typeof(WorkItemCancelException))]
+ public void CancelCancelledWorkItemAbort()
+ {
+ ManualResetEvent waitToStart = new ManualResetEvent(false);
+
+ SmartThreadPool stp = new SmartThreadPool();
+ IWorkItemResult wir = stp.QueueWorkItem(
+ state => { waitToStart.Set(); while (true) { Thread.Sleep(1000); } return null; }
+ );
+
+ waitToStart.WaitOne();
+
+ wir.Cancel(false);
+
+ Assert.IsTrue(wir.IsCanceled);
+
+ bool completed = stp.WaitForIdle(1000);
+
+ Assert.IsFalse(completed);
+
+ wir.Cancel(true);
+
+ try
+ {
+ wir.GetResult();
+ }
+ finally
+ {
+ stp.Shutdown();
+ }
+ }
+
+
///
/// 1. Create STP
/// 2. Queue work item that:
@@ -191,6 +232,7 @@ namespace SmartThreadPoolTests
stp.WaitForIdle();
+ // Throws WorkItemCancelException
wir.GetResult();
stp.Shutdown();
@@ -428,459 +470,5 @@ namespace SmartThreadPoolTests
stp.Shutdown();
}
-
- //////////////////////////////////////////////////////////////////////////////////////////////////
-/*
- private int _counter;
-
- ///
- /// Example of how to queue a work item and then cancel it while it is in the queue.
- ///
- [Test]
- [ExpectedException(typeof(WorkItemCancelException))]
- public void WorkItemCanceling()
- {
- // Create a SmartThreadPool with only one thread.
- // It just to show how to use the work item canceling feature
- SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 1);
-
- // Queue a work item that will occupy the thread in the pool
- IWorkItemResult wir1 =
- smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
-
- // Queue another work item that will wait for the first to complete
- IWorkItemResult wir2 =
- smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
-
- // Wait a while for the thread pool to start executing the first work item
- Thread.Sleep(100);
-
- try
- {
- // The first work item cannot be canceled since it is currently executing
- if (!wir1.Cancel())
- {
- // Cancel the second work item while it still in the queue
- if (wir2.Cancel())
- {
- // Retreiving result of a canceled work item throws WorkItemCancelException exception
- wir2.GetResult();
- }
- }
- }
- finally
- {
- smartThreadPool.Shutdown();
- }
- }
-
- ///
- ///
- [Test]
- public void WorkItemCancelingAndInUseWorkerThreads()
- {
- SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 10);
-
- IWorkItemResult [] wirs = new IWorkItemResult[100];
- for(int i = 0; i < 100; ++i)
- {
- wirs[i] = smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
- }
-
- // Wait a while for the thread pool to start executing the first work item
- Thread.Sleep(100);
-
- for(int i = 0; i < 100; ++i)
- {
- wirs[i].Cancel();
- }
-
- smartThreadPool.WaitForIdle(2000);
-
- int inUseThreads = smartThreadPool.InUseThreads;
-
- smartThreadPool.Shutdown();
-
- Assert.AreEqual(0, inUseThreads);
- }
-
- private object DoSomeWork(object state)
- {
- Thread.Sleep(1000);
- return 1;
- }
-
- ///
- /// Check within the work item if it was cancelled
- ///
- [Test]
- public void SampleIfWorkItemCancelled()
- {
- _counter = 0;
- STPStartInfo stpStartInfo = new STPStartInfo();
- stpStartInfo.StartSuspended = true;
-
- // Create a SmartThreadPool with only one thread.
- SmartThreadPool smartThreadPool = new SmartThreadPool(stpStartInfo);
-
- IWorkItemResult[] wirs = new IWorkItemResult[100];
- for (int i = 0; i < 100; ++i)
- {
- wirs[i] = smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoCheckForCancelledWorkItem), null);
- }
-
- for (int i = 0; i < 50; ++i)
- {
- wirs[i].Cancel();
- }
-
- smartThreadPool.Start();
-
- smartThreadPool.WaitForIdle();
-
- smartThreadPool.Shutdown();
-
- Assert.AreEqual(50, _counter);
- }
-
-
- ///
- /// 1. Create STP
- /// 2. Queue work item into the STP
- /// 4. Cancel the work item
- /// 5. Work item doesn't check for cancel
- /// 6. Work item quits
- /// 7. Make sure the work item result is ok, and not an exception
- ///
- [Test]
- public void TestWorkItemCancelledWorkItemOK()
- {
- // Create a SmartThreadPool with only one thread.
- SmartThreadPool smartThreadPool = new SmartThreadPool();
-
- AutoResetEvent start = new AutoResetEvent(false);
-
- // Queue the work item
- IWorkItemResult wir = smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoWaitForCancel), start);
-
- // Wait for it to start executing
- bool success = start.WaitOne(3000, false);
-
- // Make sure it was started
- Assert.IsTrue(success);
-
- // Cancel the work item
- wir.Cancel();
-
- // Let it complete
- start.Set();
-
- // Wait for the work item to complete
- smartThreadPool.WaitForIdle();
-
- // Check the work item's result
- // The work item started running after it was start its execution.
- // Since the work item didn't sample the cancel, it was not aware that it
- // was canceled. Therefore the result should be what the work item returned
- // and not the cancel exeception
- int result = (int)wir.GetResult(0, false);
-
- smartThreadPool.Shutdown();
-
- Assert.AreEqual(1, result);
- }
-
-
- ///
- /// 1. Create STP
- /// 2. Create WIG
- /// 3. Queue work item into the WIG
- /// 4. Cancel the work items in the WIG
- /// 5. Work item doesn't check for cancel
- /// 6. Work item quits
- /// 7. Make sure the work item result is ok, and not an exception
- ///
- [Test]
- public void TestWIGCancelledWorkItemOK()
- {
- // Create a SmartThreadPool with only one thread.
- SmartThreadPool smartThreadPool = new SmartThreadPool();
-
- IWorkItemsGroup wig = smartThreadPool.CreateWorkItemsGroup(1);
-
- AutoResetEvent start = new AutoResetEvent(false);
-
- // Queue the work item
- IWorkItemResult wir = wig.QueueWorkItem(new WorkItemCallback(this.DoWaitForCancel), start);
-
- // Wait for it to start executing
- bool success = start.WaitOne(3000, false);
-
- // Make sure it was started
- Assert.IsTrue(success);
-
- // Cancel the work item
- wig.Cancel();
-
- // Let it complete
- start.Set();
-
- // Wait for the work item to complete
- smartThreadPool.WaitForIdle();
-
- // Check the work item's result
- // The work item started running after it was start its execution.
- // Since the work item didn't sample the cancel, it was not aware that it
- // was canceled. Therefore the result should be what the work item returned
- // and not the cancel exeception
- int result = (int)wir.GetResult(0, false);
-
- smartThreadPool.Shutdown();
-
- Assert.AreEqual(1, result);
- }
-
-
- ///
- /// 1. Create STP
- /// 2. Queue work item into the STP
- /// 3. Cancel the work items in the STP
- /// 4. Work item doesn't check for cancel
- /// 5. Work item quits
- /// 6. Make sure the work item result is ok, and not an exception
- ///
- [Test]
- public void TestSTPCancelledWorkItemOK()
- {
- // Create a SmartThreadPool with only one thread.
- SmartThreadPool smartThreadPool = new SmartThreadPool();
-
- AutoResetEvent start = new AutoResetEvent(false);
-
- // Queue the work item
- IWorkItemResult wir = smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoWaitForCancel), start);
-
- // Wait for it to start executing
- bool success = start.WaitOne(3000, false);
-
- // Make sure it was started
- Assert.IsTrue(success);
-
- // Cancel the work item
- smartThreadPool.Cancel();
-
- // Let it complete
- start.Set();
-
- // Wait for the work item to complete
- smartThreadPool.WaitForIdle();
-
- // Check the work item's result
- // The work item started running after it was start its execution.
- // Since the work item didn't sample the cancel, it was not aware that it
- // was canceled. Therefore the result should be what the work item returned
- // and not the cancel exeception
- int result = (int)wir.GetResult(0, false);
-
- smartThreadPool.Shutdown();
-
- Assert.AreEqual(1, result);
- }
-
-
- ///
- /// 1. Create STP
- /// 2. Queue work item
- /// 3. Cancel the work item
- /// 4. Work item checks the cancel and quits
- /// 5. Make sure the work item result throws exception
- ///
- [Test]
- [ExpectedException(typeof(WorkItemCancelException))]
- public void TestWorkItemCanceledWorkItemCancelException()
- {
- // Create a SmartThreadPool with only one thread.
- SmartThreadPool smartThreadPool = new SmartThreadPool();
-
- AutoResetEvent start = new AutoResetEvent(false);
-
- // Queue the work item
- IWorkItemResult wir = smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoCheckForCancel), start);
-
- // Wait for it to start executing
- bool success = start.WaitOne(3000, false);
-
- // Make sure it was started
- Assert.IsTrue(success);
-
- // Cancel the work item
- wir.Cancel();
-
- // Let it complete
- start.Set();
-
- // Wait for the work item to complete
- smartThreadPool.WaitForIdle();
-
- try
- {
- // Check the work item's result
- // The work item started running after it was start its execution.
- // The work item samples the cancel, therefore it is aware that it
- // was canceled. Using the GetResult should throw the cancel exeception
- wir.GetResult(0, false);
- }
- finally
- {
- smartThreadPool.Shutdown();
- }
- }
-
- ///
- /// 1. Create STP
- /// 2. Create WIG
- /// 3. Queue work item into the WIG
- /// 4. Cancel the work items in the WIG
- /// 5. Work item checks the cancel and quits
- /// 6. Make sure the work item result throws exception
- ///
- [Test]
- [ExpectedException(typeof(WorkItemCancelException))]
- public void TestWIGCancelledWorkItemCancelException()
- {
- // Create a SmartThreadPool with only one thread.
- SmartThreadPool smartThreadPool = new SmartThreadPool();
-
- IWorkItemsGroup wig = smartThreadPool.CreateWorkItemsGroup(1);
-
- AutoResetEvent start = new AutoResetEvent(false);
-
- // Queue the work item
- IWorkItemResult wir = wig.QueueWorkItem(new WorkItemCallback(this.DoCheckForCancel), start);
-
- // Wait for it to start executing
- bool success = start.WaitOne(3000, false);
-
- // Make sure it was started
- Assert.IsTrue(success);
-
- // Cancel the work item
- wig.Cancel();
-
- // Let it complete
- start.Set();
-
- // Wait for the work item to complete
- smartThreadPool.WaitForIdle();
-
- try
- {
- // Check the work item's result
- // The work item started running after it was start its execution.
- // The work item samples the cancel, therefore it is aware that it
- // was canceled. Using the GetResult should throw the cancel exeception
- wir.GetResult(0, false);
- }
- finally
- {
- smartThreadPool.Shutdown();
- }
- }
-
- ///
- /// 1. Create STP
- /// 3. Queue work item into the STP
- /// 4. Cancel the work items in the STP
- /// 5. Work item checks the cancel and quits
- /// 6. Make sure the work item result throws exception
- ///
- [Test]
- [ExpectedException(typeof(WorkItemCancelException))]
- public void TestSTPCancelledWorkItemCancelException()
- {
- // Create a SmartThreadPool with only one thread.
- SmartThreadPool smartThreadPool = new SmartThreadPool();
-
- AutoResetEvent start = new AutoResetEvent(false);
-
- // Queue the work item
- IWorkItemResult wir = smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoCheckForCancel), start);
-
- // Wait for it to start executing
- bool success = start.WaitOne(3000, false);
-
- // Make sure it was started
- Assert.IsTrue(success);
-
- // Cancel the work item
- smartThreadPool.Cancel();
-
- // Let it complete
- start.Set();
-
- // Wait for the work item to complete
- smartThreadPool.WaitForIdle();
-
- try
- {
- // Check the work item's result
- // The work item started running after it was start its execution.
- // The work item samples the cancel, therefore it is aware that it
- // was canceled. Using the GetResult should throw the cancel exeception
- wir.GetResult(0, false);
-
- }
- finally
- {
- smartThreadPool.Shutdown();
- }
- }
-
- private object DoCheckForCancelledWorkItem(object state)
- {
- if (!SmartThreadPool.IsWorkItemCanceled)
- {
- Interlocked.Increment(ref _counter);
- }
-
- return null;
- }
-
- private object DoWaitForCancel(object state)
- {
- AutoResetEvent start = state as AutoResetEvent;
-
- // Signal the test that the work item started
- start.Set();
-
- // Let the test run (or else the next line may reset the signaled event)
- Thread.Sleep(10);
-
- // Wait for the test to cancel the work item
- start.WaitOne();
-
- return 1;
- }
-
- private object DoCheckForCancel(object state)
- {
- AutoResetEvent start = state as AutoResetEvent;
-
- // Signal the test that the work item started
- start.Set();
-
- // Let the test run (or else the next line may reset the signaled event)
- Thread.Sleep(10);
-
- // Wait for the test to cancel the work item
- start.WaitOne();
-
- // Sample if the work item was cancelled
- bool cancelled = SmartThreadPool.IsWorkItemCanceled;
-
- return 1;
- }
- */
- }
-
+ }
}
diff --git a/SmartThreadPool/WorkItem.cs b/SmartThreadPool/WorkItem.cs
index 3b24b4a..bbacc80 100644
--- a/SmartThreadPool/WorkItem.cs
+++ b/SmartThreadPool/WorkItem.cs
@@ -5,22 +5,22 @@ using System.Diagnostics;
namespace Amib.Threading.Internal
{
///
- /// Holds a callback delegate and the state for that delegate.
- ///
- public partial class WorkItem : IHasWorkItemPriority
- {
- #region WorkItemState enum
+ /// Holds a callback delegate and the state for that delegate.
+ ///
+ public partial class WorkItem : IHasWorkItemPriority
+ {
+ #region WorkItemState enum
- ///
- /// Indicates the state of the work item in the thread pool
- ///
+ ///
+ /// Indicates the state of the work item in the thread pool
+ ///
private enum WorkItemState
- {
- InQueue = 0, // Nexts: InProgress, Canceled
- InProgress = 1, // Nexts: Completed, Canceled
- Completed = 2, // Stays Completed
- Canceled = 3, // Stays Canceled
- }
+ {
+ InQueue = 0, // Nexts: InProgress, Canceled
+ InProgress = 1, // Nexts: Completed, Canceled
+ Completed = 2, // Stays Completed
+ Canceled = 3, // Stays Canceled
+ }
private static bool IsValidStatesTransition(WorkItemState currentState, WorkItemState nextState)
{
@@ -47,19 +47,19 @@ namespace Amib.Threading.Internal
return valid;
}
- #endregion
+ #endregion
- #region Fields
+ #region Fields
- ///
- /// Callback delegate for the callback.
- ///
- private readonly WorkItemCallback _callback;
+ ///
+ /// Callback delegate for the callback.
+ ///
+ private readonly WorkItemCallback _callback;
- ///
- /// State with which to call the callback delegate.
- ///
- private object _state;
+ ///
+ /// State with which to call the callback delegate.
+ ///
+ private object _state;
#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
///
@@ -68,56 +68,56 @@ namespace Amib.Threading.Internal
private readonly CallerThreadContext _callerContext;
#endif
///
- /// Holds the result of the mehtod
- ///
- private object _result;
+ /// Holds the result of the mehtod
+ ///
+ private object _result;
///
/// Hold the exception if the method threw it
///
private Exception _exception;
- ///
- /// Hold the state of the work item
- ///
- private WorkItemState _workItemState;
+ ///
+ /// Hold the state of the work item
+ ///
+ private WorkItemState _workItemState;
- ///
- /// A ManualResetEvent to indicate that the result is ready
- ///
+ ///
+ /// A ManualResetEvent to indicate that the result is ready
+ ///
private ManualResetEvent _workItemCompleted;
- ///
- /// A reference count to the _workItemCompleted.
- /// When it reaches to zero _workItemCompleted is Closed
- ///
- private int _workItemCompletedRefCount;
+ ///
+ /// A reference count to the _workItemCompleted.
+ /// When it reaches to zero _workItemCompleted is Closed
+ ///
+ private int _workItemCompletedRefCount;
- ///
- /// Represents the result state of the work item
- ///
- private readonly WorkItemResult _workItemResult;
+ ///
+ /// Represents the result state of the work item
+ ///
+ private readonly WorkItemResult _workItemResult;
- ///
- /// Work item info
- ///
- private readonly WorkItemInfo _workItemInfo;
+ ///
+ /// Work item info
+ ///
+ private readonly WorkItemInfo _workItemInfo;
- ///
- /// Called when the WorkItem starts
- ///
- private event WorkItemStateCallback _workItemStartedEvent;
+ ///
+ /// Called when the WorkItem starts
+ ///
+ private event WorkItemStateCallback _workItemStartedEvent;
- ///
- /// Called when the WorkItem completes
- ///
- private event WorkItemStateCallback _workItemCompletedEvent;
+ ///
+ /// Called when the WorkItem completes
+ ///
+ private event WorkItemStateCallback _workItemCompletedEvent;
- ///
- /// A reference to an object that indicates whatever the
- /// WorkItemsGroup has been canceled
- ///
- private CanceledWorkItemsGroup _canceledWorkItemsGroup = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
+ ///
+ /// A reference to an object that indicates whatever the
+ /// WorkItemsGroup has been canceled
+ ///
+ private CanceledWorkItemsGroup _canceledWorkItemsGroup = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
///
/// A reference to an object that indicates whatever the
@@ -125,10 +125,10 @@ namespace Amib.Threading.Internal
///
private CanceledWorkItemsGroup _canceledSmartThreadPool = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
- ///
- /// The work item group this work item belong to.
- ///
- private readonly IWorkItemsGroup _workItemsGroup;
+ ///
+ /// The work item group this work item belong to.
+ ///
+ private readonly IWorkItemsGroup _workItemsGroup;
///
/// The thread that executes this workitem.
@@ -141,9 +141,9 @@ namespace Amib.Threading.Internal
///
private long _expirationTime;
- #region Performance Counter fields
+ #region Performance Counter fields
+
-
///
@@ -156,103 +156,103 @@ namespace Amib.Threading.Internal
///
private Stopwatch _processingStopwatch;
- #endregion
+ #endregion
- #endregion
+ #endregion
- #region Properties
+ #region Properties
- public TimeSpan WaitingTime
- {
- get
- {
+ public TimeSpan WaitingTime
+ {
+ get
+ {
return _waitingOnQueueStopwatch.Elapsed;
- }
- }
+ }
+ }
- public TimeSpan ProcessTime
- {
- get
- {
+ public TimeSpan ProcessTime
+ {
+ get
+ {
return _processingStopwatch.Elapsed;
- }
- }
+ }
+ }
internal WorkItemInfo WorkItemInfo
{
- get
+ get
{
return _workItemInfo;
}
}
- #endregion
+ #endregion
- #region Construction
+ #region Construction
- ///
- /// Initialize the callback holding object.
- ///
+ ///
+ /// 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.
- ///
- /// We assume that the WorkItem object is created within the thread
- /// that meant to run the callback
- public WorkItem(
- IWorkItemsGroup workItemsGroup,
- WorkItemInfo workItemInfo,
- WorkItemCallback callback,
- object state)
- {
- _workItemsGroup = workItemsGroup;
- _workItemInfo = workItemInfo;
+ /// Callback delegate for the callback.
+ /// State with which to call the callback delegate.
+ ///
+ /// We assume that the WorkItem object is created within the thread
+ /// that meant to run the callback
+ public WorkItem(
+ IWorkItemsGroup workItemsGroup,
+ WorkItemInfo workItemInfo,
+ 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);
- }
+ if (_workItemInfo.UseCallerCallContext || _workItemInfo.UseCallerHttpContext)
+ {
+ _callerContext = CallerThreadContext.Capture(_workItemInfo.UseCallerCallContext, _workItemInfo.UseCallerHttpContext);
+ }
#endif
- _callback = callback;
- _state = state;
- _workItemResult = new WorkItemResult(this);
- Initialize();
- }
+ _callback = callback;
+ _state = state;
+ _workItemResult = new WorkItemResult(this);
+ Initialize();
+ }
- internal void Initialize()
- {
+ 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;
+ _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)
- {
- return (workItemsGroup == _workItemsGroup);
- }
+ internal bool WasQueuedBy(IWorkItemsGroup workItemsGroup)
+ {
+ return (workItemsGroup == _workItemsGroup);
+ }
- #endregion
+ #endregion
- #region Methods
+ #region Methods
- internal CanceledWorkItemsGroup CanceledWorkItemsGroup
- {
- get { return _canceledWorkItemsGroup; }
- set { _canceledWorkItemsGroup = value; }
- }
+ internal CanceledWorkItemsGroup CanceledWorkItemsGroup
+ {
+ get { return _canceledWorkItemsGroup; }
+ set { _canceledWorkItemsGroup = value; }
+ }
internal CanceledWorkItemsGroup CanceledSmartThreadPool
{
@@ -260,86 +260,86 @@ namespace Amib.Threading.Internal
set { _canceledSmartThreadPool = value; }
}
- ///
- /// Change the state of the work item to in progress if it wasn't canceled.
- ///
- ///
- /// Return true on success or false in case the work item was canceled.
- /// If the work item needs to run a post execute then the method will return true.
- ///
- public bool StartingWorkItem()
- {
+ ///
+ /// Change the state of the work item to in progress if it wasn't canceled.
+ ///
+ ///
+ /// Return true on success or false in case the work item was canceled.
+ /// If the work item needs to run a post execute then the method will return true.
+ ///
+ public bool StartingWorkItem()
+ {
_waitingOnQueueStopwatch.Stop();
_processingStopwatch.Start();
- lock(this)
- {
- if (IsCanceled)
- {
+ lock (this)
+ {
+ if (IsCanceled)
+ {
bool result = false;
- if ((_workItemInfo.PostExecuteWorkItemCallback != null) &&
+ if ((_workItemInfo.PostExecuteWorkItemCallback != null) &&
((_workItemInfo.CallToPostExecute & CallToPostExecute.WhenWorkItemCanceled) == CallToPostExecute.WhenWorkItemCanceled))
- {
- result = true;
- }
+ {
+ result = true;
+ }
return result;
- }
+ }
- Debug.Assert(WorkItemState.InQueue == GetWorkItemState());
+ 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);
- }
+ SetWorkItemState(WorkItemState.InProgress);
+ }
- return true;
- }
+ return true;
+ }
- ///
- /// Execute the work item and the post execute
- ///
- public void Execute()
- {
+ ///
+ /// Execute the work item and the post execute
+ ///
+ public void Execute()
+ {
CallToPostExecute currentCallToPostExecute = 0;
- // Execute the work item if we are in the correct state
- switch(GetWorkItemState())
- {
- case WorkItemState.InProgress:
- currentCallToPostExecute |= CallToPostExecute.WhenWorkItemNotCanceled;
- ExecuteWorkItem();
- break;
- case WorkItemState.Canceled:
- currentCallToPostExecute |= CallToPostExecute.WhenWorkItemCanceled;
- break;
- default:
- Debug.Assert(false);
- throw new NotSupportedException();
- }
+ // Execute the work item if we are in the correct state
+ switch (GetWorkItemState())
+ {
+ case WorkItemState.InProgress:
+ currentCallToPostExecute |= CallToPostExecute.WhenWorkItemNotCanceled;
+ ExecuteWorkItem();
+ break;
+ case WorkItemState.Canceled:
+ currentCallToPostExecute |= CallToPostExecute.WhenWorkItemCanceled;
+ break;
+ default:
+ Debug.Assert(false);
+ throw new NotSupportedException();
+ }
// Run the post execute as needed
- if ((currentCallToPostExecute & _workItemInfo.CallToPostExecute) != 0)
- {
- PostExecute();
- }
+ if ((currentCallToPostExecute & _workItemInfo.CallToPostExecute) != 0)
+ {
+ PostExecute();
+ }
_processingStopwatch.Stop();
- }
+ }
- internal void FireWorkItemCompleted()
- {
- try
- {
- if (null != _workItemCompletedEvent)
- {
- _workItemCompletedEvent(this);
- }
- }
- catch // Suppress exceptions
- {}
- }
+ internal void FireWorkItemCompleted()
+ {
+ try
+ {
+ if (null != _workItemCompletedEvent)
+ {
+ _workItemCompletedEvent(this);
+ }
+ }
+ catch // Suppress exceptions
+ { }
+ }
internal void FireWorkItemStarted()
{
@@ -392,7 +392,7 @@ namespace Amib.Threading.Internal
if (null == executionThread)
{
// Oops! we are going to be aborted..., Wait here so we can catch the ThreadAbortException
- Thread.Sleep(60*1000);
+ Thread.Sleep(60 * 1000);
// If after 1 minute this thread was not aborted then let it continue working.
}
@@ -425,100 +425,100 @@ namespace Amib.Threading.Internal
}
}
- ///
- /// Runs the post execute callback
- ///
- private void PostExecute()
- {
- if (null != _workItemInfo.PostExecuteWorkItemCallback)
- {
+ ///
+ /// Runs the post execute callback
+ ///
+ private void PostExecute()
+ {
+ if (null != _workItemInfo.PostExecuteWorkItemCallback)
+ {
try
{
_workItemInfo.PostExecuteWorkItemCallback(_workItemResult);
}
- catch (Exception e)
+ catch (Exception e)
{
Debug.Assert(null != e);
}
- }
- }
+ }
+ }
- ///
- /// 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
+ ///
+ /// 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;
+ internal void SetResult(object result, Exception exception)
+ {
+ _result = result;
_exception = exception;
- SignalComplete(false);
- }
+ SignalComplete(false);
+ }
- ///
- /// Returns the work item result
- ///
- /// The work item result
- internal IWorkItemResult GetWorkItemResult()
- {
- return _workItemResult;
- }
+ ///
+ /// Returns the work item result
+ ///
+ /// The work item result
+ internal IWorkItemResult GetWorkItemResult()
+ {
+ return _workItemResult;
+ }
- ///
- /// Wait for all work items to complete
- ///
+ ///
+ /// Wait for all work items to complete
+ ///
/// 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
- ///
+ /// 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 waitableResults has completed; otherwise false.
- ///
- internal static bool WaitAll(
+ ///
+ internal static bool WaitAll(
IWaitableResult[] waitableResults,
- int millisecondsTimeout,
- bool exitContext,
- WaitHandle cancelWaitHandle)
- {
+ int millisecondsTimeout,
+ bool exitContext,
+ WaitHandle cancelWaitHandle)
+ {
if (0 == waitableResults.Length)
- {
- return true;
- }
+ {
+ return true;
+ }
- bool success;
+ bool success;
WaitHandle[] waitHandles = new WaitHandle[waitableResults.Length];
GetWaitHandles(waitableResults, waitHandles);
- if ((null == cancelWaitHandle) && (waitHandles.Length <= 64))
- {
+ if ((null == cancelWaitHandle) && (waitHandles.Length <= 64))
+ {
success = STPEventWaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
- }
- else
- {
- success = true;
- int millisecondsLeft = millisecondsTimeout;
+ }
+ else
+ {
+ success = true;
+ int millisecondsLeft = millisecondsTimeout;
Stopwatch stopwatch = Stopwatch.StartNew();
- WaitHandle [] whs;
- if (null != cancelWaitHandle)
- {
- whs = new WaitHandle [] { null, cancelWaitHandle };
- }
- else
- {
- whs = new WaitHandle [] { null };
- }
+ WaitHandle[] whs;
+ if (null != cancelWaitHandle)
+ {
+ whs = new WaitHandle[] { null, cancelWaitHandle };
+ }
+ else
+ {
+ whs = new WaitHandle[] { null };
+ }
bool waitInfinitely = (Timeout.Infinite == millisecondsTimeout);
- // Iterate over the wait handles and wait for each one to complete.
- // We cannot use WaitHandle.WaitAll directly, because the cancelWaitHandle
- // won't affect it.
- // Each iteration we update the time left for the timeout.
+ // Iterate over the wait handles and wait for each one to complete.
+ // 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 < waitableResults.Length; ++i)
- {
+ {
// WaitAny don't work with negative numbers
if (!waitInfinitely && (millisecondsLeft < 0))
{
@@ -526,113 +526,113 @@ namespace Amib.Threading.Internal
break;
}
- whs[0] = waitHandles[i];
+ whs[0] = waitHandles[i];
int result = STPEventWaitHandle.WaitAny(whs, millisecondsLeft, exitContext);
if ((result > 0) || (STPEventWaitHandle.WaitTimeout == result))
- {
- success = false;
- break;
- }
+ {
+ success = false;
+ break;
+ }
- if(!waitInfinitely)
- {
+ if (!waitInfinitely)
+ {
// Update the time left to wait
millisecondsLeft = millisecondsTimeout - (int)stopwatch.ElapsedMilliseconds;
- }
- }
- }
- // Release the wait handles
+ }
+ }
+ }
+ // Release the wait handles
ReleaseWaitHandles(waitableResults);
- return success;
- }
+ return success;
+ }
- ///
- /// Waits for any of the work items in the specified array to complete, cancel, or timeout
- ///
+ ///
+ /// Waits for any of the work items in the specified array to complete, cancel, or timeout
+ ///
/// 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
- ///
- /// 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(
+ /// 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
+ ///
+ /// 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(
IWaitableResult[] waitableResults,
- int millisecondsTimeout,
- bool exitContext,
- WaitHandle cancelWaitHandle)
- {
- WaitHandle [] waitHandles;
+ int millisecondsTimeout,
+ bool exitContext,
+ WaitHandle cancelWaitHandle)
+ {
+ WaitHandle[] waitHandles;
- if (null != cancelWaitHandle)
- {
+ if (null != cancelWaitHandle)
+ {
waitHandles = new WaitHandle[waitableResults.Length + 1];
GetWaitHandles(waitableResults, waitHandles);
waitHandles[waitableResults.Length] = cancelWaitHandle;
- }
- else
- {
+ }
+ else
+ {
waitHandles = new WaitHandle[waitableResults.Length];
GetWaitHandles(waitableResults, waitHandles);
- }
+ }
int result = STPEventWaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
- // Treat cancel as timeout
- if (null != cancelWaitHandle)
- {
+ // Treat cancel as timeout
+ if (null != cancelWaitHandle)
+ {
if (result == waitableResults.Length)
- {
+ {
result = STPEventWaitHandle.WaitTimeout;
- }
- }
+ }
+ }
ReleaseWaitHandles(waitableResults);
- return result;
- }
+ return result;
+ }
- ///
- /// Fill an array of wait handles with the work items wait handles.
- ///
+ ///
+ /// Fill an array of wait handles with the work items wait handles.
+ ///
/// An array of work item results
- /// An array of wait handles to fill
- private static void GetWaitHandles(
+ /// An array of wait handles to fill
+ private static void GetWaitHandles(
IWaitableResult[] waitableResults,
- WaitHandle [] waitHandles)
- {
+ WaitHandle[] waitHandles)
+ {
for (int i = 0; i < waitableResults.Length; ++i)
- {
+ {
WorkItemResult wir = waitableResults[i].GetWorkItemResult() as WorkItemResult;
Debug.Assert(null != wir, "All waitableResults must be WorkItemResult objects");
- waitHandles[i] = wir.GetWorkItem().GetWaitHandle();
- }
- }
+ waitHandles[i] = wir.GetWorkItem().GetWaitHandle();
+ }
+ }
- ///
- /// Release the work items' wait handles
- ///
+ ///
+ /// Release the work items' wait handles
+ ///
/// An array of work item results
private static void ReleaseWaitHandles(IWaitableResult[] waitableResults)
- {
+ {
for (int i = 0; i < waitableResults.Length; ++i)
- {
+ {
WorkItemResult wir = (WorkItemResult)waitableResults[i].GetWorkItemResult();
- wir.GetWorkItem().ReleaseWaitHandle();
- }
- }
+ wir.GetWorkItem().ReleaseWaitHandle();
+ }
+ }
- #endregion
-
- #region Private Members
+ #endregion
+
+ #region Private Members
private WorkItemState GetWorkItemState()
- {
+ {
lock (this)
{
if (WorkItemState.Completed == _workItemState)
@@ -659,56 +659,56 @@ namespace Amib.Threading.Internal
return _workItemState;
}
- }
+ }
- ///
- /// Sets the work item's state
- ///
- /// The state to set the work item to
- private void SetWorkItemState(WorkItemState workItemState)
- {
- lock(this)
- {
+ ///
+ /// Sets the work item's state
+ ///
+ /// The state to set the work item to
+ private void SetWorkItemState(WorkItemState workItemState)
+ {
+ lock (this)
+ {
if (IsValidStatesTransition(_workItemState, workItemState))
{
- _workItemState = workItemState;
+ _workItemState = workItemState;
}
- }
- }
+ }
+ }
- ///
- /// Signals that work item has been completed or canceled
- ///
- /// Indicates that the work item has been canceled
- private void SignalComplete(bool canceled)
- {
- SetWorkItemState(canceled ? WorkItemState.Canceled : WorkItemState.Completed);
- lock(this)
- {
- // If someone is waiting then signal.
- if (null != _workItemCompleted)
- {
- _workItemCompleted.Set();
- }
- }
- }
+ ///
+ /// Signals that work item has been completed or canceled
+ ///
+ /// Indicates that the work item has been canceled
+ private void SignalComplete(bool canceled)
+ {
+ SetWorkItemState(canceled ? WorkItemState.Canceled : WorkItemState.Completed);
+ lock (this)
+ {
+ // If someone is waiting then signal.
+ if (null != _workItemCompleted)
+ {
+ _workItemCompleted.Set();
+ }
+ }
+ }
- internal void WorkItemIsQueued()
- {
+ internal void WorkItemIsQueued()
+ {
_waitingOnQueueStopwatch.Start();
- }
+ }
- #endregion
-
- #region Members exposed by WorkItemResult
+ #endregion
- ///
- /// 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
+ #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(bool abortExecution)
- {
+ {
#if (_WINDOWS_CE)
if(abortExecution)
{
@@ -719,14 +719,25 @@ namespace Amib.Threading.Internal
bool signalComplete = false;
lock (this)
- {
- switch(GetWorkItemState())
- {
- case WorkItemState.Canceled:
- //Debug.WriteLine("Work item already canceled");
- success = true;
+ {
+ switch (GetWorkItemState())
+ {
+ case WorkItemState.Canceled:
+ //Debug.WriteLine("Work item already canceled");
+ 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.Completed:
//Debug.WriteLine("Work item cannot be canceled");
break;
case WorkItemState.InProgress:
@@ -746,169 +757,169 @@ namespace Amib.Threading.Internal
signalComplete = true;
}
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
+ 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;
- //Debug.WriteLine("Work item canceled");
- success = true;
+ //Debug.WriteLine("Work item canceled");
+ success = true;
break;
- }
+ }
if (signalComplete)
{
SignalComplete(true);
}
- }
+ }
return success;
- }
+ }
- ///
- /// Get the result of the work item.
- /// If the work item didn't run yet then the caller waits for the result, timeout, or cancel.
- /// In case of error the method throws and exception
- ///
- /// The result of the work item
- private object GetResult(
- int millisecondsTimeout,
- bool exitContext,
- WaitHandle cancelWaitHandle)
- {
- Exception e;
- object result = GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
- if (null != e)
- {
- throw new WorkItemResultException("The work item caused an excpetion, see the inner exception for details", e);
- }
- return result;
- }
+ ///
+ /// Get the result of the work item.
+ /// If the work item didn't run yet then the caller waits for the result, timeout, or cancel.
+ /// In case of error the method throws and exception
+ ///
+ /// The result of the work item
+ private object GetResult(
+ int millisecondsTimeout,
+ bool exitContext,
+ WaitHandle cancelWaitHandle)
+ {
+ Exception e;
+ object result = GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
+ if (null != e)
+ {
+ throw new WorkItemResultException("The work item caused an excpetion, see the inner exception for details", e);
+ }
+ return result;
+ }
- ///
- /// Get the result of the work item.
- /// If the work item didn't run yet then the caller waits for the result, timeout, or cancel.
- /// In case of error the e argument is filled with the exception
- ///
- /// The result of the work item
- private object GetResult(
- int millisecondsTimeout,
- bool exitContext,
- WaitHandle cancelWaitHandle,
- out Exception e)
- {
- e = null;
+ ///
+ /// Get the result of the work item.
+ /// If the work item didn't run yet then the caller waits for the result, timeout, or cancel.
+ /// In case of error the e argument is filled with the exception
+ ///
+ /// The result of the work item
+ private object GetResult(
+ int millisecondsTimeout,
+ bool exitContext,
+ WaitHandle cancelWaitHandle,
+ out Exception e)
+ {
+ e = null;
- // Check for cancel
- if (WorkItemState.Canceled == GetWorkItemState())
- {
- throw new WorkItemCancelException("Work item canceled");
- }
+ // Check for cancel
+ if (WorkItemState.Canceled == GetWorkItemState())
+ {
+ throw new WorkItemCancelException("Work item canceled");
+ }
- // Check for completion
- if (IsCompleted)
- {
- e = _exception;
- return _result;
- }
+ // Check for completion
+ if (IsCompleted)
+ {
+ e = _exception;
+ return _result;
+ }
- // If no cancelWaitHandle is provided
- if (null == cancelWaitHandle)
- {
- WaitHandle wh = GetWaitHandle();
+ // If no cancelWaitHandle is provided
+ if (null == cancelWaitHandle)
+ {
+ WaitHandle wh = GetWaitHandle();
bool timeout = !STPEventWaitHandle.WaitOne(wh, millisecondsTimeout, exitContext);
- ReleaseWaitHandle();
+ ReleaseWaitHandle();
- if (timeout)
- {
- throw new WorkItemTimeoutException("Work item timeout");
- }
- }
- else
- {
- WaitHandle wh = GetWaitHandle();
+ if (timeout)
+ {
+ throw new WorkItemTimeoutException("Work item timeout");
+ }
+ }
+ else
+ {
+ WaitHandle wh = GetWaitHandle();
int result = STPEventWaitHandle.WaitAny(new WaitHandle[] { wh, cancelWaitHandle });
- ReleaseWaitHandle();
+ ReleaseWaitHandle();
- switch(result)
- {
- case 0:
- // The work item signaled
- // Note that the signal could be also as a result of canceling the
- // work item (not the get result)
- break;
- case 1:
+ switch (result)
+ {
+ case 0:
+ // The work item signaled
+ // Note that the signal could be also as a result of canceling the
+ // work item (not the get result)
+ break;
+ case 1:
case STPEventWaitHandle.WaitTimeout:
- throw new WorkItemTimeoutException("Work item timeout");
- default:
- Debug.Assert(false);
- break;
+ throw new WorkItemTimeoutException("Work item timeout");
+ default:
+ Debug.Assert(false);
+ break;
- }
- }
+ }
+ }
- // Check for cancel
- if (WorkItemState.Canceled == GetWorkItemState())
- {
- throw new WorkItemCancelException("Work item canceled");
- }
+ // Check for cancel
+ if (WorkItemState.Canceled == GetWorkItemState())
+ {
+ throw new WorkItemCancelException("Work item canceled");
+ }
- Debug.Assert(IsCompleted);
+ Debug.Assert(IsCompleted);
- e = _exception;
+ e = _exception;
- // Return the result
- return _result;
- }
+ // Return the result
+ return _result;
+ }
- ///
- /// A wait handle to wait for completion, cancel, or timeout
- ///
- private WaitHandle GetWaitHandle()
- {
- lock(this)
- {
- if (null == _workItemCompleted)
- {
+ ///
+ /// A wait handle to wait for completion, cancel, or timeout
+ ///
+ private WaitHandle GetWaitHandle()
+ {
+ lock (this)
+ {
+ if (null == _workItemCompleted)
+ {
_workItemCompleted = EventWaitHandleFactory.CreateManualResetEvent(IsCompleted);
- }
- ++_workItemCompletedRefCount;
- }
- return _workItemCompleted;
- }
+ }
+ ++_workItemCompletedRefCount;
+ }
+ return _workItemCompleted;
+ }
- private void ReleaseWaitHandle()
- {
- lock(this)
- {
- if (null != _workItemCompleted)
- {
- --_workItemCompletedRefCount;
- if (0 == _workItemCompletedRefCount)
- {
- _workItemCompleted.Close();
- _workItemCompleted = null;
- }
- }
- }
- }
+ private void ReleaseWaitHandle()
+ {
+ lock (this)
+ {
+ if (null != _workItemCompleted)
+ {
+ --_workItemCompletedRefCount;
+ if (0 == _workItemCompletedRefCount)
+ {
+ _workItemCompleted.Close();
+ _workItemCompleted = null;
+ }
+ }
+ }
+ }
- ///
- /// Returns true when the work item has completed or canceled
- ///
- private bool IsCompleted
- {
- get
- {
- lock(this)
- {
- WorkItemState workItemState = GetWorkItemState();
- return ((workItemState == WorkItemState.Completed) ||
- (workItemState == WorkItemState.Canceled));
- }
- }
- }
+ ///
+ /// Returns true when the work item has completed or canceled
+ ///
+ private bool IsCompleted
+ {
+ get
+ {
+ lock (this)
+ {
+ WorkItemState workItemState = GetWorkItemState();
+ return ((workItemState == WorkItemState.Completed) ||
+ (workItemState == WorkItemState.Canceled));
+ }
+ }
+ }
///
/// Returns true when the work item has canceled
@@ -917,65 +928,65 @@ namespace Amib.Threading.Internal
{
get
{
- lock(this)
+ lock (this)
{
return (GetWorkItemState() == WorkItemState.Canceled);
}
}
}
- #endregion
+ #endregion
- #region IHasWorkItemPriority Members
+ #region IHasWorkItemPriority Members
- ///
- /// Returns the priority of the work item
- ///
- public WorkItemPriority WorkItemPriority
- {
- get
- {
- return _workItemInfo.WorkItemPriority;
- }
- }
+ ///
+ /// Returns the priority of the work item
+ ///
+ public WorkItemPriority WorkItemPriority
+ {
+ get
+ {
+ return _workItemInfo.WorkItemPriority;
+ }
+ }
- #endregion
+ #endregion
- internal event WorkItemStateCallback OnWorkItemStarted
- {
- add
- {
- _workItemStartedEvent += value;
- }
- remove
- {
- _workItemStartedEvent -= value;
- }
- }
+ internal event WorkItemStateCallback OnWorkItemStarted
+ {
+ add
+ {
+ _workItemStartedEvent += value;
+ }
+ remove
+ {
+ _workItemStartedEvent -= value;
+ }
+ }
- internal event WorkItemStateCallback OnWorkItemCompleted
- {
- add
- {
- _workItemCompletedEvent += value;
- }
- remove
- {
- _workItemCompletedEvent -= value;
- }
- }
+ internal event WorkItemStateCallback OnWorkItemCompleted
+ {
+ add
+ {
+ _workItemCompletedEvent += value;
+ }
+ remove
+ {
+ _workItemCompletedEvent -= value;
+ }
+ }
public void DisposeOfState()
{
- if (_workItemInfo.DisposeOfStateObjects)
- {
- IDisposable disp = _state as IDisposable;
- if (null != disp)
- {
- disp.Dispose();
- _state = null;
- }
- }
+ if (_workItemInfo.DisposeOfStateObjects)
+ {
+ IDisposable disp = _state as IDisposable;
+ if (null != disp)
+ {
+ disp.Dispose();
+ _state = null;
+ }
+ }
}
}
}