在没有等待的情况下使用异步的最佳实践是什么?
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
修饰符(正如其他人所说)或推迟对线程池线程的调用。从你的问题我知道你两者都不想要。
申请
我有一个被多个项目或 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
修饰符(正如其他人所说)或推迟对线程池线程的调用。从你的问题我知道你两者都不想要。