2013-05-02 54 views
1

我有一个或多或少的方法调用三个不同的Async方法,然后返回一个包含成功消息的“Result”对象。这三种Async方法中的任何一种都可能会抛出一个SshException,所以我已将所有三个放在一个try{}catch{}内,它们会陷阱AggregateException,处理该SshException,然后返回一个失败的结果对象。如何将此同步方法转换为返回任务的方法?

由于我在.Net 4.0上,我不能使用async/await(我相信这可以轻松解决我的问题),但是我想将该方法转换为返回包含两个任务之一的任务的方法结果:

  1. 如果前三项任务都成功完成,则为“成功”。
  2. 如果任何以前的任务出现故障,则为“失败”。理想情况下,任务执行也会在第一个取消的任务中停止(例如,三个工作任务的TaskContinuationOptions.NotOnFaulted)。

下面是一些示例代码:

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; 
    } 
} 

回答

4

我会建议使用Microsoft.Bcl.Async它允许您使用async/await在.NET 4个项目。这将使你写:

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; 
    } 
} 

不这样做,你就必须使运行作为先前的延续各自的任务,并返回最后一个任务延续,或者只是把你现有的代码,敷在一个Task.Factory.StartNew调用(这也不是很好,因为那时你正在通过异步进行异步同步,这非常低效)。这会产生大量的代码,并使整体流程更加难以遵循。

+0

关于Microsoft.Bcl.Async的好消息,我不知道这是可用的! 在发布之前,我尝试了你的第二个选择(让每个任务都作为之前的延续运行),但我无法弄清楚如何从this.GetFilename()继续捕获并返回'UploadResult' if *那*任务抛出一个SshException。我错过了什么吗? – nemec 2013-05-02 18:19:26

+0

@nemec问题是你必须让每个任务检查异常,并重新引发到下一个,然后让最后的延续处理它 - 或者你需要改变中间任务的返回类型来处理它。这很丑陋,这就是为什么我说这是一个更好的方法;) – 2013-05-02 18:53:32

相关问题