C# 使用异步而不等待的最佳实践是什么? 应用

C# 使用异步而不等待的最佳实践是什么? 应用,c#,.net,multithreading,asynchronous,async-await,C#,.net,Multithreading,Asynchronous,Async Await,我有一个被多个项目或视图引用的视图模型 由于API,一些视图项目是异步的,而其他项目则不是 视图项目使用IOC容器将其接口实现注入到视图模型 代码 考虑这个代码的最小示例 界面: public interface IDatabase { Task<Data> GetData(); } 异步视图项目使用异步函数获取数据 public class AsynchronousViewDataBase : IDatabase { public async Task<Da

我有一个被多个项目或视图引用的
视图模型

由于API,一些
视图
项目是
异步的
,而其他项目则不是

视图
项目使用IOC容器将其接口实现注入到
视图模型

代码 考虑这个代码的最小示例

界面:

public interface IDatabase
{
    Task<Data> GetData();
}
异步视图
项目使用异步函数获取数据

public class AsynchronousViewDataBase : IDatabase
{
    public async Task<Data> GetData()
    {
        return await GetDataAsync();
    }
}
但是然后它会发出警告:

此异步方法缺少“await”运算符,将同步运行。考虑使用“Acess”操作符等待非阻塞API调用,或“等待任务.Run(…)”在后台线程上执行CPU绑定的工作。 这对我来说很好,因为我不在乎它是否同步运行

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

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

附加的 我确实将界面转换为同步调用,并在
异步视图中使用
Task.Result
(修复了警告),但这导致应用程序停止响应,并出现了许多困难问题


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

您的接口应该实现两种不同的方法,并让调用方决定是异步还是同步

Data GetData();


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

public class SynchronousViewDatabase : IDatabase
{
    public Task<Data> GetData()
    {
        return Task.FromResult<Data>(GetData());
    } 
}
公共类SynchronousViewDatabase:IDatabase
{
公共任务GetData()
{
返回Task.FromResult(GetData());
} 
}
是否有实现这种非等待异步方法的最佳实践

是的,它被称为同步API。不要强迫非自然异步的代码如此。添加一个
GetData
方法,该方法返回一个
字符串

可以忽略警告吗

只要你明白其中的含义就可以了。从异步方法调用可能长时间运行的同步方法可能会让此方法的使用者感到惊讶,因为它实际上会阻塞。 此外,任何异常都将通过生成的状态机
任务
进行封装。当然,还有国家机器本身和任何被提升的操作员的小开销

有更好的方法实现异步同步调用吗


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

因为FromResult中的GetData返回数据而不是任务。askers的例子似乎有点模糊。我对这个答案投了赞成票。
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;
    } 
}
public class SynchronousViewDatabase : IDatabase
{
    public Task<Data> GetData()
    {
        return Task.FromResult<Data>(GetData());
    } 
}