locked
How to cancel a task<T> cooperatively? RRS feed

  • Question

  • Hi,

    I am using the task<T> type from the ConCRT extras pack version 0.4 with VS 2010 SP1.

    In the lambda function I am passing to the task<T> in its ctor how can I check whether the task has been cancelled and return (or throw) immediately in cooperative way?

    auto t = task<long>([=]() -> long
    {
    	std::cout << "Starting calculation..." << std::endl;
    	long sum = 0;
    	for (int j = 0; j < 1000; ++j)
    	{
    		// how to check here whether the task has been canceled and return (or throw) immediately?
    		for (long i = 0; i < 1000000; ++i)
    			sum += i;
    	}
    	std::cout << "Finished calculation..." << std::endl;
    	return sum;
    });
    
    t.cancel();
    t.wait();
    
    ::Sleep(5000);
    
    

    When I run the code above, I get the "Finished calculation..." although I have canceled the task.

    Any ideas?

    Best regards,
    Bernd

     

     

     

    Friday, May 13, 2011 12:45 PM

Answers

  • Correct.

     

    The sample pack implementation does not use task_groups and as such, there are no mechanisms where you can receive a cancellation from a "parent" task_group.  For this release of the sampe pack, we don't support cancellation flowing through the context.

    We have considered how to support cancellation and the ramifications of cancelling tasks.  We would be interested in your scenario, how you will use it and what you expect should happen so that we can meet your needs in the product.  If you want, you can post that information here or contact me directly at dana dot groff at microsoft dot com. 

    As always, I am interested in how our customers are using our libraries and runtime.  I would love to hear about success stories and I want to hear about problems you have had so we can correct those problems.

    Thank you,

    Dana


    Dana Groff, Senior Program Manager Parallel Computing, Concurrency Runtime
    • Proposed as answer by Dana Groff Tuesday, May 17, 2011 5:25 PM
    • Marked as answer by RAB36 Tuesday, May 17, 2011 7:24 PM
    Tuesday, May 17, 2011 5:25 PM

All replies

  • Hi Bernd,

        is_current_task_canceling() is the api you are looking for. You could poll for the tasks cancelation status from within the for loop inside the task. Note however that there is a concept of a commit point for the cancelation. For more information, please refer to is_current_task_group_canceling Function which works quite similar to is_current_task_canceling and Cancelation in the PPL

     

    Thanks,

    Vinod.

    Monday, May 16, 2011 6:26 PM
  • Hi Vinod,

    thanks for your answer. I was not aware of is_current_task_canceling().

    But it does not seem to work (or maybe I am doing something wrong):

     

    auto t = task<long>([]() -> long
    {
    	std::cout << "Starting calculation..." << std::endl;
    	long sum = 0;
    	for (int j = 0; j < 1000; ++j)
    	{
    		if (is_current_task_canceling())
    		{
    			std::cout << "Cancelled calculation..." << std::endl;
    			return -1;
    		}
    		for (long i = 0; i < 1000000; ++i)
    			sum += i;
    	}
    	std::cout << "Finished calculation..." << std::endl;
    	return sum;
    });
    
    wait(100);
    t.cancel();
    wait(100);
    t.wait();
    
    wait(100000);
    
    

    I do not get the expected output

    Starting calculation...
    Cancelled calculation...

    but

    Starting calculation...
    Finished calculation...

    It appears to me that <ppltasks.h> (as of ConCRT extras pack 0.4 that I am using) does not use a task collection internally but leightweight tasks, wheras is_current_task_canceling() seems to depend on a task collection (as in task_group):

     

    static bool __cdecl is_current_task_canceling()
    {
     return Context::IsCurrentTaskCollectionCanceling();
    }
    
    

     

    Any ideas?

    Best regards,
    Bernd

     


    • Edited by RAB36 Tuesday, May 17, 2011 9:29 AM Missing expected output
    • Proposed as answer by Dana Groff Tuesday, May 17, 2011 5:25 PM
    • Unproposed as answer by Dana Groff Tuesday, May 17, 2011 5:25 PM
    Tuesday, May 17, 2011 9:27 AM
  • Correct.

     

    The sample pack implementation does not use task_groups and as such, there are no mechanisms where you can receive a cancellation from a "parent" task_group.  For this release of the sampe pack, we don't support cancellation flowing through the context.

    We have considered how to support cancellation and the ramifications of cancelling tasks.  We would be interested in your scenario, how you will use it and what you expect should happen so that we can meet your needs in the product.  If you want, you can post that information here or contact me directly at dana dot groff at microsoft dot com. 

    As always, I am interested in how our customers are using our libraries and runtime.  I would love to hear about success stories and I want to hear about problems you have had so we can correct those problems.

    Thank you,

    Dana


    Dana Groff, Senior Program Manager Parallel Computing, Concurrency Runtime
    • Proposed as answer by Dana Groff Tuesday, May 17, 2011 5:25 PM
    • Marked as answer by RAB36 Tuesday, May 17, 2011 7:24 PM
    Tuesday, May 17, 2011 5:25 PM
  • Dana,

    thanks for the clarification and I appreciate your interest.

    I am looking at the task type as a pattern to move compute intensive work off the UI thread.

    Imagine that you have a long running calculation with some result and you want to show some kind of progress (i.e. in the status bar of your application) and the ability to cancel the operation (either via user input or because the parameters of the calculation have changed in the meanwhile).

    So I am firing up a task, store it in a member variable and later want to cancel it. I can call cancel() on the task.

    But how do I cancel my work within the calculation? Of course I could dedicate a flag to that purpose, pass it to the lambda expression and check it.

    But that seems clumsy and doesn’t seem to compose well with sub-tasks within the task, when_all, when_any etc.

    So having a general cancellation capability (as in task_group, or with the CancellationTokenSource / CancellationToken pattern of .NET)

    would be great.

    I am sending more info about what we are trying to achieve and what other experiences I had with <ppltasks.h> in an e-mail to you.

    Best regards,
    Bernd

    Tuesday, May 17, 2011 7:24 PM
  • Dana,

    I sent you an e-mail at 5/17/2011 but did not get a response yet.

    I also tried to post a comment at http://blogs.msdn.com/b/nativeconcurrency/archive/2011/03/09/tasks-and-continuations-available-for-download-today.aspx but it did not appear.

    Therefore I opened a discussion here:

    http://social.msdn.microsoft.com/Forums/en-US/parallelcppnative/thread/fdcc0324-b5f8-4549-b7b0-bf7d276f5278

    Best regards,
    Bernd

     

     

    Friday, May 27, 2011 5:40 AM