c#正确的并行模式.对于异步等待方法
本文关键字:异步 方法 等待 于异步 并行 模式 | 更新日期: 2023-09-27 18:08:28
我想听听关于这个方法的一些建议。这是一个好的模式,还是其他的表现更好?
public async Task<PortfolioLoans> GetSampleOfPortfolioLoanNumbers(int count = 1)
{
var sqlConn = new SqlConnection(this.DataMineConnectionString);
var pfLoans = new PortfolioLoans();
var ts = new ThreadSafeList<PortfolioLoan>();
try
{
await Task.Run(() => {
Parallel.For(0, count, async i =>
{
var loans = await sqlConn.QueryAsync("dbo.spGetSampleApplicationIDs", Parameters.Empty, Query.Returns<PortfolioLoan>());
ts.AddRange(loans);
});
pfLoans.Loans.AddRange(ts.Clone());
});
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
return pfLoans;
}
Parallel
类在async/await之前被释放。NOT支持使用async
in作为方法主体。当你使用async
时,它创建了一个匿名的async void
函数,因为它不能告诉你什么时候工作完成了,它在你开始的任务完成之前就完成了。使用async/await的一组更现代的类是TPL Dataflow。
其次sqlConn
不是线程安全的,你不能在多个线程同时使用它。你必须为每个线程创建一个新的连接对象。
最后,我会把钱放在pfLoans.Loans
是List<T>
或类似的东西,不是线程安全的。不能从多个线程调用不是为处理来自多个线程的调用而设计的函数。你必须锁定对AddRange
的调用,或者用一个线程安全的类替换掉这个类。
稍微清理一下并添加线程安全:
public async Task<PortfolioLoans> GetSampleOfPortfolioLoanNumbers(int count = 1)
{
var pfLoans;
try
{
pfLoans = await Task.Run(async () => {
var sqlConn = new SqlConnection(this.DataMineConnectionString);
var pls = new Portfolioloans();
for(var i=0; i<count; i++)
{
var loans = await sqlConn.QueryAsync("dbo.spGetSampleApplicationIDs", Parameters.Empty, Query.Returns<PortfolioLoan>());
pls.Loans.AddRange(loans);
}
return pls;
});
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
return pfLoans;
}
除非这些查询花费太长时间,否则我不知道是否会将它们放在并行中。
编辑:我错过了sqlConn.QueryAsync
上的异步,如果担心阻塞,那么你甚至不需要一个任务,因为QueryAsync
已经是异步的。
public async Task<PortfolioLoans> GetSampleOfPortfolioLoanNumbers(int count = 1)
{
var pfLoans = new PortfolioLoan();
try
{
var sqlConn = new SqlConnection(this.DataMineConnectionString);
var pls = new Portfolioloans();
for(var i=0; i<count; i++)
{
var loans = await sqlConn.QueryAsync("dbo.spGetSampleApplicationIDs", Parameters.Empty, Query.Returns<PortfolioLoan>());
pfLoans.Loans.AddRange(loans);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
return pfLoans;
}