【发布时间】:2014-12-05 21:22:53
【问题描述】:
我的问题是基于一个真实的项目问题,但我从未使用过 System.Threading.Tasks 库或执行任何涉及线程的严肃编程,所以我的问题可能是缺乏对特定库的了解和对什么的更普遍的误解就编程而言,异步确实意味着。
所以我的真实情况是这样的 - 我需要获取有关用户的数据。在我目前的情况下,它是财务数据,所以假设我需要某个用户的所有Accounts、所有Deposits 和所有Consignations。在我的情况下,这意味着要为每个属性查询数百万条记录,并且每个查询本身相对较慢,但是获取Accounts 比获取Deposits 慢几倍。所以我为我要使用的三种银行产品定义了三个类,当我想获取某个用户的所有银行产品的数据时,我会这样做:
List<Account> accounts = GetAccountsForClient(int clientId);
List<Deposit> deposits = GetDepositsForClient(int clientId);
List<Consignation> consignations = GetConsignationsForClient(int clientId);
所以问题从这里开始,我需要同时获取所有这三个列表,因为我要将它们传递给显示所有用户数据的视图。但是现在执行是同步的(如果我在这里正确使用了该术语),因此收集所有三种产品的数据的总时间是:
Total_Time = Time_To_Get_Accounts + Time_To_Get_Deposits + Time_To_Get_Consignations
这不好,因为每个查询都比较慢,所以总时间相当长,而且,accounts 查询比其他两个查询花费更多的时间,所以今天进入我脑海的想法是 - “如果我可以同时执行这些查询会怎样”。也许这是我对这个话题最大的误解,但对我来说,最接近这个想法的是让它们异步所以也许Total_Time 不会是最慢查询的时间,但会比所有三个的总和快得多查询。
由于我的代码很复杂,我创建了一个简单的用例,我认为它可以很好地反映我正在努力做的事情。我有两种方法:
public static async Task<int> GetAccounts()
{
int total1 = 0;
using (SqlConnection connection = new SqlConnection(connString))
{
string query1 = "SELECT COUNT(*) FROM [MyDb].[dbo].[Accounts]";
SqlCommand command = new SqlCommand(query1, connection);
connection.Open();
for (int i = 0; i < 19000000; i++)
{
string s = i.ToString();
}
total1 = (int) await command.ExecuteScalarAsync();
Console.WriteLine(total1.ToString());
}
return total1;
}
第二种方法:
public static async Task<int> GetDeposits()
{
int total2 = 0;
using (SqlConnection connection = new SqlConnection(connString))
{
string query2 = "SELECT COUNT(*) FROM [MyDb].[dbo].[Deposits]";
SqlCommand command = new SqlCommand(query2, connection);
connection.Open();
total2 = (int) await command.ExecuteScalarAsync();
Console.WriteLine(total2.ToString());
}
return total2;
}
我这样称呼:
static void Main(string[] args)
{
Console.WriteLine(GetAccounts().Result.ToString());
Console.WriteLine(GetDeposits().Result.ToString());
}
如您所见,我首先调用GetAccounts(),并故意减慢执行速度,因此我给了执行机会以继续下一个方法。但是我在一段时间内没有得到任何结果,然后我同时在控制台上打印出来。
所以问题-如何使我不等待第一个方法完成,以便转到下一个方法。一般来说,代码结构并不那么重要,我真正想弄清楚的是是否有任何方法可以使两个查询同时执行。这里的示例是我的研究结果,也许可以扩展到我会得到想要的结果的地步。
附言
我使用ExecuteScalarAsync(); 只是因为我从使用它的方法开始。实际上我会使用Scalar 和Reader。
【问题讨论】:
-
您应该使用
await connection.OpenAsync();,因此连接设置也是异步完成的。
标签: c# multithreading ado.net task-parallel-library async-await