locked
Returning result from canceled task RRS feed

  • Question


  • When task is completed I can simple do:

    var res = await task;


    When task is canceled I can only catch TaskCanceledException.

    I have in mind workaround to pass to async method "boxed" params (ref are denied in async).. Are there other ways?

    Sergey.
    Monday, February 14, 2011 7:20 AM

Answers

  • Hi Sergey-

    Unfortunately your proposed solution of subclassing TaskCanceledException won't work, as the additional data associated with your exception will be lost, at least in the current implementation.  All operation canceled exceptions are translated into the returned task being canceled, and the exception gets thrown away.  We'll consider your comment and whether we should modify that design.

    Tuesday, February 15, 2011 5:17 AM
    Moderator

All replies

  • Hi Sergunok-

    If a task is canceled, it has no result, so there's no value for "await task" to return, and thus the OperationCanceledException is thrown.  What outcome are you expecting here?  And, more generally, what are you trying to achieve?

    Monday, February 14, 2011 8:13 AM
    Moderator
  • Hi Stephen,

     

    That's what I have:

     

    async Task<int> SendAll(int n, CancellationToken ct)

    {

       int i = 0;

       while(i < n)

      {

         await Send(ct); // takes time can be canceled via ct

         i++;

      }

      return i;

    }

     

    The code which calls and awaits SendAll should get number requests successfully sent.

     

    Here is work-around:

    class Boxed<T>

    {

      public T Value;

    }

     

    async Task SendAll(int n, Boxed<int> i, CancellationToken ct)

    {

      i.Value = 0;

      while(i.Value < n)

      {

         await Send(ct); // takes time can be canceled via ct

         i.Value++;

      }

    }

     

     


    Sergey.
    Monday, February 14, 2011 8:35 AM
  • I see. So you really want to treat the CancellationToken as a notification that the operation is done and partial results should be returned, rather than that the whole operation is going to be ignored.  In that case, why not just wrap a try/catch around the "await Send(ct);", and if an OperationCanceledException emerges, return whatever i value you have?  Of course, your Boxed<int> works as well.
    Monday, February 14, 2011 2:58 PM
    Moderator
  • I see. So you really want to treat the CancellationToken as a notification that the operation is done and partial results should be returned, rather than that the whole operation is going to be ignored.  In that case, why not just wrap a try/catch around the "await Send(ct);", and if an OperationCanceledException emerges, return whatever i value you have?  Of course, your Boxed<int> works as well.

    The reason is that I have liked "propagation if cancellation" in async code. It matches my domain and is suitable.. 

     

    I have also other idea - to inherit TaskCanceledException,add Result field to subclass and wrap "await Send(ct)" so:

    try

    {

      await Send(ct);

    }

    catch(TaskCanceledException)

    {

      throw new TaskCanceledExceptionWithResult(i);

    }

     

    but not sure this will work (for example not sure that async method will be in IsCanceled state after throwing such exception etc.)


    Sergey.
    Monday, February 14, 2011 3:20 PM
  • Hi Sergey-

    Unfortunately your proposed solution of subclassing TaskCanceledException won't work, as the additional data associated with your exception will be lost, at least in the current implementation.  All operation canceled exceptions are translated into the returned task being canceled, and the exception gets thrown away.  We'll consider your comment and whether we should modify that design.

    Tuesday, February 15, 2011 5:17 AM
    Moderator