C#Paralle的正确模式。用于异步等待方法

时间:2016-09-23 17:16:14

标签: c# async-await task-parallel-library

我想就这种方法提出一些建议。这是一个很好的模式,还是会有更好的表现?

    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;
    }

2 个答案:

答案 0 :(得分:1)

在异步/等待之前,Parallel类被重新发送。它使用async作为boday方法支持 NOT 。当您使用async时,它会创建一个非常async void的函数,因此它无法判断工作何时完成,并且在您完成任务之前完成。使用async / await的更现代的一组类是TPL Dataflow

其次sqlConn不是线程安全的, 你不能同时从多个线程使用它。 你必须为每个线程创建一个新的连接对象线程。

最后,我会把钱花在pfLoans.LoansList<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