none
Multi-Threading Cross-Class Cancellation with TPL

    Question

  • All, I have a long running process that I run on a background thread (with cancellation support) using the Task Paralell Library (TPL). The code for this long running taks is contained within `Class Validation`, and when the method

        public bool AsyncRunValidationProcess(TaskScheduler _uiScheduler, 
            CancellationToken _token, dynamic _dynamic = null)
         {
             try
             {
     
                // Note: _uiScheduler is used to update the UI thread with progress infor etc.
     
                for (int i = 0; i < someLargeLoopNumber; i++)
                 {
                     // Cancellation requested from UI Thread.
                     if (_token.IsCancellationRequested) 
                        _token.ThrowIfCancellationRequested();
                 }
                 return true;
             }
             catch (Exception eX)
             {
                 // Do stuff. Display `eX` if cancellation requested.
                 return false;
             }
         }

    is run from `Class Validation` I can cancel the process fine. The cancellation request is handled by the appropriate `delegate` (shown below). However, when I run this method from another class via another method `asyncControlMethod()`, the cancellation stops working. The controller is invoked via

        asyncTask = Task.Factory.StartNew<bool>(() => asyncControlMethod(), token);

    which in turn invokes the method

    valForm.AsyncRunValidationProcess(uiScheduler, token, 
            new List<string>() { strCurrentSiteRelPath }));

    where `valForm` is my accessor to `Class Validation`, the method runs fine, but when I attempt a cancellation the `delegate`

        cancelHandler = delegate 
        {
             UtilsTPL.CancelRunningProcess(asyncTask, cancelSource);
         };

    where

        public static void CancelRunningProcess(Task _task, 
            CancellationTokenSource _cancelSource)
         {
             try
             {
                 _cancelSource.Cancel();
                 _task.Wait(); // On cross-class call it freezes here.
             }
             catch (AggregateException aggEx)
             {
                 if (aggEx.InnerException is OperationCanceledException)
                     Utils.InfoMsg("Operation cancelled at users request.");
                 if (aggEx.InnerException is SqlException)
                     Utils.ErrMsg(aggEx.Message);
             }
         }

    freezes/hangs (with no unhandled exception etc.) on `_task.Wait()`. This I think is to do with the fact that I am cancelling `asyncControlMethod()` which has called `valForm.AsyncRunValidationProcess(...)`, so it is cancelling `asyncControlMethod()` which is causing the current process to hang.

    **I know I am probably being stupid here, but can anyone tell me what I am doing wrong or should be doing to allow such a cancellation proceedure?**

    _Note: I have tried to spawn a child task to run `valForm.AsyncRunValidationProcess(...)`, with its own `CancellationToken` but this has not worked._

    Thanks for your time.


    "Everything should be made as simple as possible, but not simpler" - Einstein



    Monday, May 14, 2012 2:13 PM

Answers

All replies