将并行或任务与web服务和数据库连接一起使用
本文关键字:数据库连接 一起 服务 web 并行 任务 | 更新日期: 2023-09-27 18:06:06
解释
我有一个场景,我有1000个客户,他们的信息存储在不同的区域,我需要从一个地方检索他们的交易他们的余额来自另一个,他们的信息来自本地源
前2个(交易和余额(使用Web服务,本地信息是一个正常的数据库SqlConnection
在运行每个客户之前,我会检索余额列表,因为每个客户都有一个余额条目,但每个客户必须检索客户交易,其余的计算取决于
我需要了解每个客户,并在他们的账户上做一些事情,比如如果交易符合某些标准,就发放奖金或扣除,每月发放免费积分等等。
需要对帐户执行的每一项操作都需要一个新的数据库或web调用来更新该资源
所以代码看起来像这样(psuedo(
var Clients = getfromDB();
var Balances = webservicecall.getbalances();
var clientswithbalances = from balance in Balances
join customer in Clients on balance.Idnumber equals customer["IdNumber"]
orderby Convert.ToInt32(customer["CustomerId"])
select new
{
CustomerId = Convert.ToInt32(customer["CustomerId"]),
Name = customer["Name"].ToString(),
Idnumber = customer["Idnumber"].ToString(),
Balance = Convert.ToDouble(balance.Value, CultureInfo.InvariantCulture)
};
foreach (var user in users)
{
var transactions = webcalltransactions(user.Idnumber);
//calculations that use more webservices and database calls updates and inserts
}
问题
我尝试了parallel.foreach,但它在Web服务和数据库调用方面出现了问题
做到这一点的最佳方法是什么?
您可以制作一个控制台应用程序来测试这一点,但仅适用于.net 4.5>=。这也可以在其他版本上完成,但需要进行一些更改。
class Program
{
static void Main(string[] args)
{
DoStuff().Wait();//As you can see my main thread is blocked if wait is used;
Console.WriteLine("Done");
Console.ReadLine();
}
public static async Task DoStuff()
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
var clientsTask = GetFromDBAsync(); //DON'T await
var balancesTask = GetBalancesAsync(); //DON'T await
await Task.WhenAll(clientsTask, balancesTask);//If the implementation is async dose a parallel call the nameing convention is async methods have Async at the end MethodAsync
var clients = clientsTask.Result;
var balances = balancesTask.Result;
var users = Enumerable.Range(clients, balances).Select(i=>new { IdNumber = i }); // I am mocking your query so you can see what is happening
var usersTasks = users.Select(user => GetClientAsync(user.IdNumber)).ToArray();
var userServerData = await Task.WhenAll(usersTasks);//You can do Task.WaitAll(usersTasks) if your method can't be async but this will block you main thread and can be buggy ;
foreach (var user in userServerData)
{
Console.WriteLine(user);
}
sw.Stop();
Console.WriteLine("Total time {0}", sw.ElapsedMilliseconds);//Total time is close to 2s rather then 22s if everething is sync;
}
public static Task<int> GetFromDBAsync()
{
return Task.Delay(1000).ContinueWith(t => 0);
}
public static Task<int> GetBalancesAsync()
{
return Task.Delay(1000).ContinueWith(t => 20);
}
public static Task<int> GetClientAsync(int clientId)
{
return Task.Delay(1000).ContinueWith(t => clientId);
}
}