65.9K
CodeProject 正在变化。 阅读更多。
Home

简化异步调用

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.78/5 (9投票s)

2014 年 2 月 2 日

CPOL
viewsIcon

51685

downloadIcon

304

如何减少调用异步方法的开销和复杂性。

引言

我经常会回顾旧代码,看看我是如何实现异步调用的。
不止一次,我想到可以将 async “内容”封装起来,这样我就不需要记住如何实现了。 

本文介绍的是如何将 async 调用封装成更容易记忆的东西。  

典型的异步用法 

这个例子展示了我通常如何实现一个异步调用。

  public void Backup()
  {
    backupInProgress = true;
    Task<String> backup = BackupAsync();
    backup.GetAwaiter().OnCompleted(
      () =>
      {
        BackupStatus = backup.Result;
        backupInProgress = false;
      });
  }  

其中 BackupAsync 处理异步和 await

  private async Task<String> BackupAsync()
  {
    Func<string> a = () =>
      {
        // Do stuff here
      };
    return await Task.Run(a);
  } 

我通常使用 Function/TaskResult 来更新逻辑或 UI,当异步方法完成时。  在上面的例子中,设置了一个属性 BackupStatus 。 

减少代码   

异步调用可以封装到以下方法中: 
  public static void Do(Func<T> func, Action<T> completed)
  {
    Task<T> task = AsyncTask(func);
    task.GetAwaiter().OnCompleted(() =>
                                  {
                                    if (!task.IsFaulted) // Check if Faulted
                                      completed(task.Result);
                                  });
  } 

其中 AsyncTask 定义如下

  private static async Task<T> AsyncTask(Func<T> func)
  {
    return await Task.Run(func);
  } 

现在我可以异步调用一个函数 (func),并将结果传递给一个 Action (completed),使用以下代码

  Async<string>.Do(Backup, UpdateUI); 

其中 Backup 和 UpdateUI 是常规方法,以异步方式调用: 

  private string Backup()
  {
    // Do backup
    return "Done"; // return status
  } 

  private void UpdateUI(string status)
  {
    BackupStatus = status;
  } 

完美!不再需要 async await,但是我们如何处理异常呢?
嗯,我们可以创建一个重载,如果 Task 具有 IsFaulted 设置,则调用另一个方法

  public static void Do(Func<T> func, Action<T> completed, Action<Exception> failure)
  {
    Task<T> task = AsyncTask(func);
    task.GetAwaiter().OnCompleted(() =>
      {
        if (task.IsFaulted)
          failure(task.Exception);
        else
          completed.Invoke(task.Result);
      });
  } 
这样我们就可以像这样调用 Do 方法
  Async<string>.Do(Backup, UpdateUI, HandleException);  

其中 HandleException: 

  private void HandleException(Exception parameter)
  {
     // Handle exception
  }  


请查看提供的示例以获取更多信息。 

历史 

我最初的想法。

© . All rights reserved.