1
votes

I have a method that more or less calls three different Async methods and then returns a "Result" object containing a success message. Any of those three Async methods may throw a SshException, so I've placed all three within a try{}catch{} that traps the AggregateException, handles the SshException, and then returns a failure result object.

Since I'm on .Net 4.0, I can't use async/await (which I believe would solve my problem easily), but I would like to turn the method into one that returns a Task containing one of two results:

  1. "Success" if all three previous tasks completed successfully.
  2. "Failure" if any of the previous tasks faulted. Ideally, task execution would stop at the first canceled task too (e.g. TaskContinuationOptions.NotOnFaulted for the three work Tasks).

Here's some sample code:

public UploadResult UploadFileToDir(string dir, string text)
{
    try
    {
        SftpClient.Cd(dir).Wait();  // This is a Task
        var filename = this.GetFilename().Result;  // This is also a Task
        SftpClient.WriteFile(filename, text).Result;  // This is the last Task
        return UploadResult.Success;
    }
    catch(AggregateException agg)
    {
        if(agg.InnerException is SshException)
        {
            return UploadResult.Failure;
        }
        throw;
    }
}
1

1 Answers

4
votes

I would recommend using Microsoft.Bcl.Async which allows you to use async/await in .NET 4 projects. That would allow you to write:

public async Task<UploadResult> UploadFileToDir(string dir, string text)
{
    try
    {
        await SftpClient.Cd(dir)
        var filename = await this.GetFilename();
        await SftpClient.WriteFile(filename, text);
        return UploadResult.Success;
    }
    catch(SshException ex)
    {
        return UploadResult.Failure;
    }
}

Without that, you'd have to make each task run as a continuation on the previous, and return the final Task continuation, or just take your existing code and wrap it in a Task.Factory.StartNew call (which isn't really good either, as you're then doing async over sync over async, which is very inefficient). This creates a lot of code, and makes the overall flow much more difficult to follow.