2016-09-23 42 views
-1

我想就此方法提供一些建議。這是一個很好的模式,還是會有其他更好的表現?C#Paralle.For異步等待方法的正確模式

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

是'pfLoans.Loans'的一個列表?如果是這樣的話不是線程安全的 –

+0

@AndrewMorton - 我正在使用[Insight Database](https://github.com/jonwagner/Insight.Database)micro orm – chdev77

+0

@ DanielA.White - 感謝您指出這一點。我會解決這個問題。 – chdev77

回答

0

要清理一下,添加線程安全:

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

除非這些查詢的時間太長,我不知道我是否還會把它們放在一個的Parallel.For

編輯:我錯過了異步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; 
} 
+0

通過visual studio來運行代碼,你在Task.Run(()=> {'中的'()之前忘記了一個異步了, –

+0

@ScottChamberlain是的,謝謝,我完全掩蓋了異步查詢 –

+0

因此,我應該使用'await Task.Run(async()=>'嗎?一個小混亂在這裏,我真的很感謝所有的反饋。 – chdev77

1

Parallel這個類在before async/await之前被重新傳遞。它確實不是支持使用async作爲今天的方法。當您使用async時,它會創建一個聲名狼借的async void函數,並且因爲它無法分辨工作何時完成,並且在完成啓動的任務之前完成。與異步/等待一起工作的更現代的一組類是TPL Dataflow

其次sqlConn不是線程安全的,你不能在多個線程同時使用它。您必須爲每個線程創建一個新的連接對象。

最後我會把錢放在那pfLoans.Loans是一個List<T>或類似的東西,不是線程安全的。您不能從多個線程中調用不用於處理來自多個線程的調用的函數。您必須鎖定對AddRange的調用,或將線程安全更改爲類。

+0

現在你提到它了,我已經體驗了你用'Paralle.For'和'async'提到的確切scenerio。現在我知道它爲什麼在做它正在做的事情。謝謝 – chdev77