【发布时间】:2020-11-04 10:30:46
【问题描述】:
我想完全了解如何在 TAP 中实现 async 和 await 关键字。我遇到了这个 MSDN 条目:https://docs.microsoft.com/en-us/dotnet/csharp/async
在这篇文章中,您可以阅读以下两个陈述:
对于 I/O 绑定代码,您等待在异步方法中返回任务或任务的操作。
在编写任何代码之前,您应该问两个问题:
您的代码会“等待”某事,例如来自数据库的数据吗?
如果您的回答是“是”,那么您的工作是 I/O 绑定的。
您的代码会执行昂贵的计算吗?
如果您回答“是”,那么您的工作受 CPU 限制。
如果您的工作受 I/O 限制,请使用 async 和 await 而不使用 Task.Run。您不应使用任务并行库。其原因在 Async in Depth 中有概述。
链接的文章是https://docs.microsoft.com/en-us/dotnet/standard/async-in-depth
但我不明白,为什么我不应该使用 Task.Run 从数据库中获取数据。
我的意思是对于大多数方法,我可以简单地使用异步计数器部分,例如 ExecuteNonQueryAsync 或 ExecuteScalarAsync
但是我应该如何使用数据适配器来获取 DataTable。考虑以下方法
public DataTable SelectData(string selectCommand)
{
OpenConnection();
DataTable data = new DataTable();
Command.CommandType = CommandType.Text;
Command.CommandText = selectCommand;
using (MySqlDataAdapter adapter = new MySqlDataAdapter(Command))
{
adapter.Fill(data);
}
CloseConnection();
return data;
}
我建议使用以下方法来异步获取我的数据,但根据 MSDN 上的帖子,我不知道这是否是正确的方法。
public async Task<DataTable> SelectDataAsync(string selectCommand)
{
return await Task.Run(() => SelectData(selectCommand));
}
此外,考虑以下方法:
public void Query(string sqlCommand)
{
OpenConnection();
Command.CommandText = sqlCommand;
Command.CommandType = CommandType.Text;
Command.ExecuteNonQuery();
CloseConnection();
}
如果我想同时支持异步和同步,我该如何编写这个方法?我的意思是我可以写两次相同的代码,但我没有调用同步方法,而是使用异步方法。
public async QueryAsync(string sqlCommand)
{
OpenConnection();
Command.CommandText = sqlCommand;
Command.CommandType = CommandType.Text;
await Command.ExecuteNonQueryAsync();
CloseConnection();
}
同样的场景。我不应该将 Task.Run 用于 I/O-Bound 工作,但我不想两次编写几乎相同的代码。
谁能澄清如何正确地做到这一点?
【问题讨论】:
-
但我不明白,为什么我应该使用 Task.Run 从数据库中获取数据。 你应该使用
await和async进行交互一个数据库,而不是Task.Run,你可能弄错了。 -
调用者中的代码无法将使用非异步版本的 Query 转换为您的 QueryAsync 函数。减少重复的一种选择是使 QueryAsync 成为主要功能,并在使用 Query 的地方用 Task.Result 包装它。
-
@imsmn 哦,对不起,我应该放在那里而不是不应该放在那里。我编辑了我的主要帖子。
-
“我建议使用以下方法来获取我的数据异步” - 这种方法不会真正让您的数据“异步”。您当前的线程在等待
Task.Run的结果时被释放,但另一个线程池线程(Task.Run)被阻塞,等待SelectData完成,所以最后 - 什么都没有实现。如果你想要两个版本 - 最好只留下Asyncvesrion,因为调用者可以在适当的情况下同步等待它的结果,但是你不能从同步版本中获取异步版本(Task.Run没有按照描述的那样做)。
标签: c# asynchronous async-await