New Posts New Posts RSS Feed: Coroutine Error Handling
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Coroutine Error Handling

 Post Reply Post Reply
Author
ken.nelson View Drop Down
Groupie
Groupie


Joined: 03-Mar-2009
Location: Ann Arbor, MI
Posts: 54
Post Options Post Options   Quote ken.nelson Quote  Post ReplyReply Direct Link To This Post Topic: Coroutine Error Handling
    Posted: 16-Mar-2011 at 8:05am
Is it necessary to error check each coroutine operation's error state after each yield return or is it eoungh to handle errors in the Coroutine completed callback?  (Is the red highlighted code below necessary?)
 
Without the use of a Coroutine, my code would look something like the following, with error checked after each async call has completed:
 

private void LoadData() {

     em.Customers.Where().ExecuteAsync((customerArgs) =>
     {
          if (customerArgs.HasError) { // handle error }
          else
          {
               em.Orders.Where().ExecuteAsync((orderArgs) =>
               {
                    if (orderArgs.HasError) { // handle error }
                    else
                    {
 
                    }
               });
          }
     });
}
 
Translating to Coroutine, my code is:
 

private void LoadData()
{
     Coroutine.Start(CoroutineActions, (completed) =>
     {
          if (completed.HasError) { // handle error }
          else
          {
 
          }
     });
}
 
private IEnumerable<INotifyCompleted> CoroutineActions()
{
     var op1 = em.Customers.Where().ExecuteAsync();
     yield return op1;
 
     // Do I have to continue to error check after each async operation, or
     // is it ok to skip this?
     if (op1.HasError) { // handle error }
     else
     {
          var op2 = em.Orders.Where().ExecuteAsync();
          yield return op2;
     }
}
 
Back to Top
sbelini View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 13-Aug-2010
Location: Oakland
Posts: 786
Post Options Post Options   Quote sbelini Quote  Post ReplyReply Direct Link To This Post Posted: 16-Mar-2011 at 12:13pm
Hi Ken,
 
It is always a good idea, and the developers responsability, to check for errors.
 
On a coroutine operation you should check for errors before yielding to the Coroutine consumer:
 
////////////////////////////////////////////////////////////////////////////////////////
private IEnumerable<INotifyCompleted> LoadTopCustomersCoroutine() {

  var userId = CurrentUser.UserId;

  var allCustOperation = Manager.Customers.ExecuteAsync();

  // event handler
  var allCustOperation.Completed += (s1, args1) => {
    if (args1.HasError) HandleError(args1);
  };

  yield return allCustOperation; // SUSPEND
  // more code
}
////////////////////////////////////////////////////////////////////////////////////////
 
or
 
////////////////////////////////////////////////////////////////////////////////////////
private IEnumerable<INotifyCompleted> LoadTopCustomersCoroutine() {
  var allCustOperation = Manager.Customers.ExecuteAsync(
     // Callback checks for error
     op => { if (op.HasError) HandleError(op); }
    );

  yield return allCustOperation; 
  // more code
}
////////////////////////////////////////////////////////////////////////////////////////
 
 
If an error occurs, you can let the error bubble up to the outer Coroutine or you can take care of the exception and mark the error as handled:
 
 
You will also find this information in our DevForce Resource Center.
 
Regards,
   Silvio.


Edited by sbelini - 16-Mar-2011 at 12:16pm
Back to Top
mikewishart View Drop Down
Groupie
Groupie
Avatar

Joined: 26-Feb-2010
Location: Reno, NV
Posts: 49
Post Options Post Options   Quote mikewishart Quote  Post ReplyReply Direct Link To This Post Posted: 17-Mar-2011 at 9:38am
Ken, write yourself some extension methods such as:

    /// <summary>
    /// Same as ExecuteAsync() except it tests for an error before returning the result
    /// </summary>
    public static EntityQueryOperation<T> ExecuteAsyncResult<T>(this IEntityQuery<T> query,
      Action<IEnumerable<T>> userCallback)
    {
      return query.ExecuteAsync(op => CheckExecuteAsyncResult(op, userCallback), null);
    }

    /// <summary>
    /// Same as ExecuteAsync() except it tests for an error before returning the result
    /// </summary>
    public static EntityQueryOperation<T> ExecuteAsyncResult<T>(this IEntityQuery<T> query,
      Action<IEnumerable<T>, object> userCallback, object userState)
    {
      return query.ExecuteAsync(op => CheckExecuteAsyncResult(op, r => userCallback(r, op.UserState)), userState);
    }

    private static void CheckExecuteAsyncResult<T>(EntityQueryOperation<T> op,
      Action<IEnumerable<T>> userCallback)
    {
      if (op.HasError)
        throw new Exception(op.Error.Message);

      userCallback(op.Results);
    }

Back to Top
ken.nelson View Drop Down
Groupie
Groupie


Joined: 03-Mar-2009
Location: Ann Arbor, MI
Posts: 54
Post Options Post Options   Quote ken.nelson Quote  Post ReplyReply Direct Link To This Post Posted: 17-Mar-2011 at 12:50pm
This was more of a question of, "what is DevForce doing under the hood automatically?".  From the sound of it, my conclusion is that DevForce is not checking the error state of the each async operation while executing in a coroutine.  And this is perfectly ok, I just wasn't sure if it was necessary to check for errors after each operation or if it was already being done under the hood.
 
Thanks!
Back to Top
kimj View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 1391
Post Options Post Options   Quote kimj Quote  Post ReplyReply Direct Link To This Post Posted: 18-Mar-2011 at 5:02pm

DevForce does actually check for errors after each async operation, and does not call subsequent operations in the iterator block if a prior one failed, unless you've marked the error as handled.  If you set up a handler for the Coroutine completed you can see there if an error occurred, plus all the "Notifications" for each async operation up to and including the operation which failed.  You don't need to include error checking within your iterator unless you want to, or if you will be marking the error as handled so that subsquent operations can run.

Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down