我想就这种方法提出一些建议。这是一个很好的模式,还是会有更好的表现?
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;
}
答案 0 :(得分:1)
在异步/等待之前,Parallel
类被重新发送。它使用async
作为boday方法支持 NOT 。当您使用async
时,它会创建一个非常async void
的函数,因此它无法判断工作何时完成,并且在您完成任务之前完成。使用async / await的更现代的一组类是TPL Dataflow。
其次sqlConn
不是线程安全的, 你不能同时从多个线程使用它。 你必须为每个线程创建一个新的连接对象线程。
最后,我会把钱花在pfLoans.Loans
是List<T>
或类似的东西上,并且不是线程安全的。您无法从多个线程调用函数,这些线程不是为处理来自多个线程的调用而设计的。您必须锁定对AddRange
的调用或使用线程安全的类更改类。
答案 1 :(得分:0)
要稍微清理它并添加线程安全性:
/puclic/
除非这些查询花费的时间太长,否则我不知道是否会将它们放在Parallel.For
中编辑:我错过了 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