user3027752
user3027752

Reputation:

TrySetException handling

For the code below Could someone please explain Who handles tcs.TrySetException(t.Exception.InnerExceptions); exceptions? Is it thrown to the user? When EndDevide is called?

public class Calculator : ICalculator
{
  public IAsyncResult BeginDivide(uint numerator, uint denominator, AsyncCallback callback, object state)
  {
    // See the Task-Based Asynchronous Pattern document for an explanation of the Begin/End implementations.
    var tcs = new TaskCompletionSource<uint>(state);
    var task = DivideAsync(numerator, denominator);
    task.ContinueWith(t =>
    {
      if (t.IsFaulted)
        tcs.TrySetException(t.Exception.InnerExceptions);
      else if (t.IsCanceled)
        tcs.TrySetCanceled();
      else
        tcs.TrySetResult(t.Result);

      if (callback != null)
        callback(tcs.Task);
    });

    return tcs.Task;
  }

  public uint EndDivide(IAsyncResult asyncResult)
  {
    try
    {
      return ((Task<uint>)asyncResult).Result;
    }
    catch (AggregateException ex)
    {
      // Note: the original stack trace is lost by this re-throw, but it doesn't really matter.
      throw ex.InnerException;
    }
  }
}

Upvotes: 0

Views: 2508

Answers (2)

Renaud Bancel
Renaud Bancel

Reputation: 893

You need to know that the Task class and async/await is the new prefered tool for async programming. A previous async model used BeginXxx() to start an Xxx asynch operation and EndXxx() to wait the end of the asynch operation.

Today, in new code, you have to use in an async method. await resut = DivideAsync(....);

BeginDivide() and EndDivide() are provided for backward compatibility.

The Task system have the great advantage to propagate async exceptions to the caller by rethrowing an exception when the task complete and returns its result (but to pass completion/exception status to ContinueWith() code). The continue with code calls the callback at end of asynch operation and allows to wait with EndDivide() providing exactly the old paradigm that returns the exception during EndXxx().

Task internals are very interesting : Task isn't only a light mapper to threads but a complete system for handling asynchronous operations (including I/O operations). For new code only forgot the old Begin/End paradigm.

The DivideAsync() method is interesting if delegated to a "peripheral" like a GPU, a network resource... Remark : By convention we will not suffix method names creating threads with "Async" because without threads the asynchronism is lightweight but it can appear in some libraries.

Upvotes: 1

csaam
csaam

Reputation: 1367

When EndDevide is called it would be thrown back to the user. Why aren't you using the 4.5 async await instead of the older Begin/End syntax? The code is much simpler then. It's fact the whole thing boils down to await DivideAsync(numerator, denominator);

Upvotes: 1

Related Questions