在没有等待的情况下使用异步的最佳实践是什么?

What is the best practice using async without await?

申请

我有一个被多个项目或 Views 引用的 View Model

由于 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 项目使用异步函数获取数据

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

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

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

但是然后它给出警告:

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

这对我来说有点好,因为我不在乎它是否同步运行。

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

问题

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

额外

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

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

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

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

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

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

Is there a best practice to implement this type of non-await async method?

是的,它被称为 同步 API。不要强制非自然异步的代码如此。添加一个 GetData 方法,其中 returns 一个 string.

Is it okay to ignore the warning?

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

Is there a better way to implement the async Synchronous call?

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