在没有等待的情况下使用async的最佳做法是什么?

Bar*_*kkr 8 .net c# multithreading asynchronous async-await

应用

我有一个View Model由多个项目引用或Views.

由于API,一些View项目是,async而另一些则不是.

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

考虑这个代码的最小例子

界面:

public interface IDatabase
{
    Task<Data> GetData();
}
Run Code Online (Sandbox Code Playgroud)

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...
     }
}
Run Code Online (Sandbox Code Playgroud)

Asynchronous View project使用Async函数来获取数据

public class AsynchronousViewDataBase : IDatabase
{
    public async Task<Data> GetData()
    {
        return await GetDataAsync();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

public class SynchronousViewDatabase : IDatabase
{
    public async Task<Data> GetData()
    {
        return GetData();
    } 
}
Run Code Online (Sandbox Code Playgroud)

随后它发出警告:

这种异步方法缺少"等待"运算符并将同步运行.考虑使用'await'运算符等待非阻塞API调用,或'await Task.Run(...)'在后台线程上执行CPU绑定工作.

这对我很好,因为我不在乎它是否同步运行.

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

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

额外

我做了接口转换为同步调用,并使用Task.ResultAsynchronous View(其中固定的警告),但导致该应用程序停止响应,只是很多难以解决的问题.

注意:我并未声明使用async关键字神奇地使方法异步运行.

Ned*_*nov 10

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

public class SynchronousViewDatabase : IDatabase
{
    public Task<Data> GetData()
    {
        return Task.FromResult<Data>(GetData());
    } 
}
Run Code Online (Sandbox Code Playgroud)


Yuv*_*kov 6

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

是的,它被称为同步API.不要强制非自然异步的代码.添加一个GetData返回a 的方法string.

可以忽略警告吗?

这是确定你理解其含意为长.调用可能从异步方法长时间运行的同步方法可能会让这个方法的消费者感到惊讶,因为它实际上会阻塞.此外,还有一个事实是,任何异常都将通过生成的状态机进行封装Task.当然,状态机本身和任何提升的运营商的开销都很小.

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

这实际上取决于用例.如果这是一个不明显的短操作,你可以放弃使用Task.FromResult和删除async修饰符(正如其他人所说)或将调用推迟到线程池线程.从你的问题我明白你也不想要.