Sequential processing of asynchronous tasks

前端 未结 5 576
旧时难觅i
旧时难觅i 2020-12-08 02:53

Assume the following synchronous code:

try
{
    Foo();
    Bar();
    Fubar();
    Console.WriteLine(\"All done\");
}
catch(Exception e) // For illustration         


        
5条回答
  •  抹茶落季
    2020-12-08 03:14

    Here's how it would work with async:

    try
    {
        await FooAsync();
        await BarAsync();
        await FubarAsync();
        Console.WriteLine("All done");
    }
    catch(Exception e) // For illustration purposes only. Catch specific exceptions!
    {
        Console.WriteLine(e);
    }
    

    This would work on .NET 4.0 if you installed the (prerelease) Microsoft.Bcl.Async package.


    Since you're stuck on VS2010, you can use a variant of Stephen Toub's Then:

    public static Task Then(this Task first, Func next)
    {
      var tcs = new TaskCompletionSource();
      first.ContinueWith(_ =>
      {
        if (first.IsFaulted) tcs.TrySetException(first.Exception.InnerExceptions);
        else if (first.IsCanceled) tcs.TrySetCanceled();
        else
        {
          try
          {
            next().ContinueWith(t =>
            {
              if (t.IsFaulted) tcs.TrySetException(t.Exception.InnerExceptions);
              else if (t.IsCanceled) tcs.TrySetCanceled();
              else tcs.TrySetResult(null);
            }, TaskContinuationOptions.ExecuteSynchronously);
          }
          catch (Exception exc) { tcs.TrySetException(exc); }
        }
      }, TaskContinuationOptions.ExecuteSynchronously);
      return tcs.Task; 
    }
    
    
    

    You can use it as such:

    var task = FooAsync().Then(() => BarAsync()).Then(() => FubarAsync());
    task.ContinueWith(t =>
    {
      if (t.IsFaulted || t.IsCanceled)
      {
        var e = t.Exception.InnerException;
        // exception handling
      }
      else
      {
        Console.WriteLine("All done");
      }
    }, TaskContinuationOptions.ExcecuteSynchronously);
    

    Using Rx, it would look like this (assuming you don't have the async methods already exposed as IObservable):

    FooAsync().ToObservable()
        .SelectMany(_ => BarAsync().ToObservable())
        .SelectMany(_ => FubarAsync().ToObservable())
        .Subscribe(_ => { Console.WriteLine("All done"); },
            e => { Console.WriteLine(e); });
    

    I think. I'm not an Rx master, by any means. :)

    提交回复
    热议问题