3

I am using Multithreading to approach my problem. I have been using Parallel.Foreach inside the background worker DoWork event where long running job has been executing. But, the problem arise when I have to cancel the job. It does not cancel the thread immediately.

BackgroundWorker DoWork event :

private void File_DoWork(object sender, DoWorkEventArgs e)
{
    var cts = new CancellationTokenSource();
    btnCancel.Click += (cancelSender, cancelEvent) =>
                {
                     bgwFile.CancelAsync();

                     if (bgwFile.CancellationPending)
                     {
                         cts.Cancel();
                         e.Cancel = true;
                     }
                };
    object sync = new object();
    List<Response> responses = null;

    var parallelOperation = new ParallelOptions
    {
          MaxDegreeOfParallelism = 3,
          CancellationToken = cts.Token
    };

    Parallel.ForEach(listRequest, parallelOperation, request =>
    {
        lock (sync)
        {
             responses = GetQueryResponse(request); // Long running process      
             parallelOperation.CancellationToken.ThrowIfCancellationRequested();
        }
    });
    e.Result = responses ;
}

Here, the problem is when I have to cancel long running job. Suppose, there is three request which has been loop through parallel.foreach having MaxDegreeOfParallelism = 3,then it goes for GetQueryResponse(request) method which is long job, if I cancel the thread using CancellationTokenSource, then it does not cancel the process immediately. It only cancel after executing 3 request thread.

I would like it to cancel it immediately. Is there any approach to cancel all running thread produced by Parallel.Foreach immediately and goes to RunWorkerCompleted event of backgroundworker?

Tony
  • 7,345
  • 3
  • 26
  • 34
Akash KC
  • 16,057
  • 6
  • 39
  • 59
  • 1
    At the very least you should ensure that your code snippets compile before posting, which cannot possibly be the case here due to `responses` being accessed outside the scope in which it is declared. – Kirill Shlenskiy Dec 24 '13 at 06:07
  • Thanks kirill..Indeed,above snippet is sample code of my actual one...Thanks for pointing out...:) – Akash KC Dec 24 '13 at 06:11
  • 1
    Uhmmm, with the lock you are using, you are doing nothing in parallel. as far I can see... – Felice Pollano Dec 24 '13 at 06:43
  • @FelicePollano : I have other operation inside parallel too. But main problem is happening with responses = GetQueryResponse(request); – Akash KC Dec 24 '13 at 07:28

3 Answers3

3

You can use CancellationToken.Register Method (Action) to Registers a delegate that will be called when this CancellationToken is canceled.

It will be fired as soon as cancellation is requested. Of course, you have to write the logic which will cause current GetQueryResponse execution stop immediately.

MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263
  • By the way, GetQueryResponse is long running IO operation(such as searching file in network).Is there any way to forcibly cancel the operation while running? – Akash KC Dec 26 '13 at 05:25
  • It depends on the operation itself. There is nothing that lets you *kill* TPL task explicitely, like you would do with `Thread` class instance. Check this answer: [How do I abort/cancel TPL Tasks?](http://stackoverflow.com/questions/4783865/how-do-i-abort-cancel-tpl-tasks). – MarcinJuraszek Dec 26 '13 at 05:27
0

Check CancellationTokens for TPL.here Passing a CancellationToken to Parallel.Foreach() can make it work. When you want to stop all tasks just use:

cts.Cancel()

Inside your Task's method place

cts.Token.ThrowIfCancellationRequested(); when you want to check if the Task needs to be stopped because another Task cancelled the process.

Pouya Samie
  • 3,718
  • 1
  • 21
  • 34
-2

You can set the IsBackground property of the thread as true. This will kill all the thread when your app finishes.

You can use one timer (or one thread), that wakes and examines the data. That should be more resource friendly.

Alps
  • 37
  • 1
  • 1
  • 7