New Posts New Posts RSS Feed: AsyncParallelTaskCompletedArgs cannot be converted to AsyncEventArgs
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

AsyncParallelTaskCompletedArgs cannot be converted to AsyncEventArgs

 Post Reply Post Reply
Author
skingaby View Drop Down
DevForce MVP
DevForce MVP
Avatar

Joined: 23-Apr-2008
Location: United States
Posts: 146
Post Options Post Options   Quote skingaby Quote  Post ReplyReply Direct Link To This Post Topic: AsyncParallelTaskCompletedArgs cannot be converted to AsyncEventArgs
    Posted: 23-Jul-2009 at 11:33am
I've created the following unit test:

[TestMethod]

[Asynchronous]
public void TestLockedMonth()
{
    _em = new DomainModel.DomainModelEntityManager();
    var task1 = AsyncSerialTask.Create();
    var task2 = task1.AddAsyncLogin(_em, new LoginCredential(null, null, null));
    var task3 = task2.AddAction(x => Assert.IsTrue(_em.IsLoggedIn));
    var task4 = task3.AddAction(x => Assert.IsTrue(_em.IsConnected));
    var task5 = task4.AddAsyncAction<AsyncParallelTaskCompletedArgs>((loginEventArgs, callback) => LocalEntityManager.InitializeCacheAsync(callback));
    EnqueueCallback(() => task5.Execute(null, args => TestLockedMonthCallback(args)));
}


The InitializeCacheAsync method looks like this:
public static void InitializeCacheAsync(Action<AsyncParallelTaskCompletedArgs> callback)

{
    var task = AsyncParallelTask.Create();
    task.AddAsyncQuery(1, x => _defaultManager.AccountingMonths);
    task.AddAsyncQuery(2, x => _defaultManager.DealTypes);
    task.Execute(callback);
}


This compiler error shows:
The type 'IdeaBlade.EntityModel.AsyncParallelTaskCompletedArgs' cannot be used as type parameter 'T2' in the generic type or method 'IdeaBlade.EntityModel.AsyncSerialTask<T0,T1>.AddAsyncAction<T2>(System.Action<T1,IdeaBlade.EntityModel.AsyncCompletedCallback<T2>>)'. There is no implicit reference conversion from 'IdeaBlade.EntityModel.AsyncParallelTaskCompletedArgs' to 'IdeaBlade.EntityModel.AsyncEventArgs'.

Is something I can work around? Thanks, Simon.
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: 23-Jul-2009 at 6:42pm
The async actions in the AsyncSerialTask expect an AsyncCompletedCallback of AsyncEventArgs or a sub-type, and unfortunately the AsyncParallelTaskCompletedArgs aren't a sub-type of AsyncEventArgs.  We'll look at fixing this.
 
Meanwhile, you can still do what you need, but with a bit more work.  Since you can't use AddAsyncAction<AsyncParallelTaskCompletedArgs> with the serial task, you need to insert a dummy action here to tie the results of the parallel task back to the serial task.  There are probably more clever ways to do this, but here's one -
 

    public void TestLockedMonth() {
      _em = new DomainModel.DomainModelEntityManager();
      var task1 = AsyncSerialTask.Create();
      var task2 = task1.AddAsyncLogin(_em1, new LoginCredential(null, null, null));
      var task3 = task2.AddAction(x => Assert.IsTrue(_em1.IsLoggedIn));
      var task4 = task3.AddAction(x => Assert.IsTrue(_em1.IsConnected));
      var task5 = task4.AddAsyncAction<AsyncEventArgs>((x, cb) => InitializeCacheAsync(cb, TestLockedMonthCallback));
      EnqueueCallback(() => task5.Execute(null, args => TestLockedMonthCallback2(args)));
    }
    // Take 2 args here - 1 the serial task callback, the other the parallel task completion action.
    public void InitializeCacheAsync(AsyncCompletedCallback<AsyncEventArgs> serialCB, Action<AsyncParallelTaskCompletedArgs> completionAction) {
      var task = AsyncParallelTask.Create();
      task.AddAsyncQuery(1, x => _defaultManager.AccountingMonths);
      task.AddAsyncQuery(2, x => _defaultManager.DealTypes);
      // Any object can be passed as input and available to the completion action.
      task.Execute(serialCB, completionAction);
    }
    // Parallel task completion action
    public void TestLockedMonthCallback(AsyncParallelTaskCompletedArgs args) {
      // We passed this callback as input parm into the AsyncParallelTask
      var serialCB = args.ExecutionInput as AsyncCompletedCallback<AsyncEventArgs>;
      // Build new args, taking advantage of userState input argument.
      AsyncEventArgs newArgs = null;
      if (args.Ok) {
        // This is arbitrary - here we supply parallel task completion info ...
        newArgs = new AsyncEventArgs(args.CompletionMap);
      } else {
        // Also arbitrary - if parallel task failed provide some info ...
        newArgs = new AsyncEventArgs(args.Errors[0].Exception, false, args.Errors);
      }
      // Now call the serial task's callback action.
      serialCB(newArgs);
    }
    // Called when serial task completes.
    public void TestLockedMonthCallback2(AsyncSerialTaskCompletedArgs<AsyncEventArgs> args) {
      // Result here is the result from the parallel task completion.
      var result = args.Result;
      var completionMap = result.UserState as Dictionary<object, AsyncEventArgs>;
      TestExit();
    }
Back to Top
skingaby View Drop Down
DevForce MVP
DevForce MVP
Avatar

Joined: 23-Apr-2008
Location: United States
Posts: 146
Post Options Post Options   Quote skingaby Quote  Post ReplyReply Direct Link To This Post Posted: 29-Jul-2009 at 6:53am
This was a really slick workaround. It works like a charm. I have even used this in the middle of a longer stack of serial tasks (i.e. calling InitializeCache and then doing some other things afterwards). Very nice. Thank you for your help!
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down