【问题标题】:What is the best practice using async without await? [duplicate]使用 async 而不使用 await 的最佳做法是什么? [复制]
【发布时间】:2015-04-10 09:19:41
【问题描述】:

应用

我有一个被多个项目引用的View ModelViews

由于 API,一些 View 项目是 async 而其他不是。

View 项目使用 IOC 容器将其接口实现注入View Model

代码

考虑这个最小的代码示例

界面:

public interface IDatabase
{
    Task<Data> GetData();
}

View Model 等待 GetData 方法:

public class DisplayDataViewModel
{
     private readonly  IDatabase _database
     public DisplayDataViewModel(IDatabase database)
     {
          _database = database;
     }

     private async Task GetDataFromDatabase()
     {
         Data data = await _database.GetData();
         // do something with data...
     }
}

Asynchronous View 项目使用 Async 函数获取数据

public class AsynchronousViewDataBase : IDatabase
{
    public async Task<Data> GetData()
    {
        return await GetDataAsync();
    }
}

Synchronous View项目使用同步调用获取数据,但是由于接口的限制,我需要返回一个Task,但我只对Data的返回感兴趣,从而使方法异步.

public class SynchronousViewDatabase : IDatabase
{
    public async Task<Data> GetData()
    {
        return GetData();
    } 
}

但是然后它给出警告:

此异步方法缺少“等待”运算符,将同步运行。考虑使用 'await' 运算符来等待非阻塞 API 调用,或使用 'await Task.Run(...)' 在后台线程上执行 CPU 密集型工作。

这对我来说还不错,因为我不在乎它是否同步运行。

使用Task.Run 来抑制警告似乎没有必要,因为调用可以(在我的情况下确实如此)来自后台线程。

问题

是否有实现这种非等待异步方法的最佳实践?可以忽略警告吗?有没有更好的方法来实现 async 同步调用?

附加

我确实将接口转换为同步调用,并在Asynchronous View 中使用了Task.Result(修复了警告),但这导致应用程序停止响应并且出现了很多难题。

注意:我不是说使用 async 关键字会神奇地使方法异步运行。

【问题讨论】:

    标签: c# .net multithreading asynchronous async-await


    【解决方案1】:

    你的接口应该实现两种不同的方法,让调用者决定他需要异步还是同步

    Data GetData();
    

    Task<Data> GetDataAsync();
    

    这是运行异步方法同步的一种可能方式

    public class SynchronousViewDatabase : IDatabase
    {
        public Data GetData()
        {
            var getDataTask = GetDataAsync();
            getDataTask.RunSynchroniously();
            if(getDataTask.Status == TaskStatus.RanToCompletion)
               return getDataTask.Result;
    
            throw getDataTask.Exception;
        } 
    }
    

    【讨论】:

      【解决方案2】:

      async 是一个实现细节,因此如果您不使用await,则可以将其从方法中删除,然后您可以使用Task.FromResult 返回已完成的任务以及所需的结果。

      public class SynchronousViewDatabase : IDatabase
      {
          public Task<Data> GetData()
          {
              return Task.FromResult<Data>(GetData());
          } 
      }
      

      【讨论】:

      • 鉴于 FromResult 中的 GetData 返回 Data 而不是 Task。提问者的例子似乎有点模糊。赞成这个答案。
      【解决方案3】:

      是否有实现这种非等待异步方法的最佳实践?

      是的,它称为同步 API。不要强制那些不是自然异步的代码是这样的。添加一个GetData 方法,该方法返回一个string

      可以忽略警告吗?

      ok只要你理解其中的含义。从异步方法调用可能长时间运行的同步方法可能会使该方法的使用者感到惊讶,因为它实际上会阻塞。 此外,任何异常都将通过生成的状态机Task 进行封装。当然还有状态机本身和任何提升的运算符的小开销。

      有没有更好的方法来实现异步同步调用?

      这真的取决于用例。如果这是一个不明显的简短操作,您可以使用Task.FromResult 并删除async 修饰符(如其他人所说)或推迟对线程池线程的调用。根据您的问题,我知道您都不想要。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-29
        • 2013-11-25
        • 1970-01-01
        • 2016-06-02
        • 1970-01-01
        • 2021-03-01
        相关资源
        最近更新 更多