How to cancel an item and then wait for it to complete?

Feb 27, 2012 at 4:41 AM

Hello,

When we shut down our app we need to cancel and wait for each each work item to complete one by one (because of the layered architecture of our app). We would like to do the following for each item:
1. Cancel work item, so that it can detect that it was cancelled and attempt to stop its work internally  - workItemResult.Cancel(false)
2. Wait at most 30 seconds for the item to stop work - pool.WaitAll(workItem, 30sec)
3. If an item does not complete then kill it by throwing ThreadAborted exception - workItemResult.Cancel(true)

The problem is that once we call workItemResult.Cancel(false) then pool.WaitAll(workItem, 30sec) no longer waits for this item for 30sec.

What is the right way to implement this with SmartThreadPool?

Thanks,

Alec

Feb 28, 2012 at 8:20 PM

I ended up using the approach implemented in SmartThreadPoolTests.TestPostExecution.DoTestPostExecuteWithCancel test. However, I needed to change the first switch case in Amib.Threading.Internal.WorkItem#Cancel(bool) to this:

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"
      signalComplete = true;
    }
  }
  success = true;
  break;

The code in BOLD above allows sending ThreadAbort to workItem that was already cancelled. This allows me to implement the following pattern:

if (wir.Cancel(false))
{
	bool completed = postExecuteResult.wh.WaitOne(ThreadTimeout, true);
	if (!completed)
	{
		smartFuture.Cancel(true);
	}
}

Could you please review the code in BOLD above and apply it as a patch?

Thanks,

Alec