2010-11-05 183 views
2

我有一個問題,實施CCR與SQL。看來,當我通過我的代碼更新和插入我試圖執行偉大的工作。但是當我通過我的界面沒有任何斷點時,它似乎正在工作,它顯示插入,更新,但在運行結束時,沒有任何更新到數據庫。微軟機器人和SQL

我開始爲我的代碼添加一個暫停,每當我從我的池中拉出一個新的線程,它的工作原理......但是,這是否違背了異步編碼的目的?我想我的接口速度更快,不會慢下來......

任何建議...這裏是我的代碼部分:

我用兩個助手類來設置我的口,並得到響應。 ..

/// <summary> 
    /// Gets the Reader, requires connection to be managed 
    /// </summary> 
    public static PortSet<Int32, Exception> GetReader(SqlCommand sqlCommand) 
    { 
     Port<Int32> portResponse = null; 
     Port<Exception> portException = null; 
     GetReaderResponse(sqlCommand, ref portResponse, ref portException); 
     return new PortSet<Int32, Exception>(portResponse, portException); 
    } 

    // Wrapper for SqlCommand's GetResponse 
    public static void GetReaderResponse(SqlCommand sqlCom, 
     ref Port<Int32> portResponse, ref Port<Exception> portException) 
    { 
     EnsurePortsExist(ref portResponse, ref portException); 
     sqlCom.BeginExecuteNonQuery(ApmResultToCcrResultFactory.Create(
      portResponse, portException, 
      delegate(IAsyncResult ar) { return sqlCom.EndExecuteNonQuery(ar); }), null); 
    } 

然後我做這樣的事情要排隊我電話......

 DispatcherQueue queue = CreateDispatcher(); 
     String[] commands = new String[2]; 
     Int32 result = 0; 
     commands[0] = "exec someupdateStoredProcedure"; 
     commands[1] = "exec someInsertStoredProcedure '" + Settings.Default.RunDate.ToString() + "'"; 

     for (Int32 i = 0; i < commands.Length; i++) 
     { 
      using (SqlConnection connSP = new SqlConnection(Settings.Default.nbfConn + ";MultipleActiveResultSets=true;Async=true")) 
      using (SqlCommand cmdSP = new SqlCommand()) 
      { 
       connSP.Open(); 
       cmdSP.Connection = connSP; 
       cmdSP.CommandTimeout = 150; 
       cmdSP.CommandText = "set arithabort on; " + commands[i]; 

       Arbiter.Activate(queue, Arbiter.Choice(ApmToCcrAdapters.GetReader(cmdSP), 
        delegate(Int32 reader) { result = reader; }, 
        delegate(Exception e) { result = 0; throw new Exception(e.Message); })); 
      } 
     } 

其中ApmToCcrAdapters是類的名字在那裏幫助我的方法是...

問題是當我在Arbiter.Activate調用後立即暫停我的代碼,並檢查我的數據庫時,一切看起來都很好......如果我擺脫了暫停廣告運行我的代碼,數據庫沒有任何反應,也沒有例外拋出...

回答

3

這裏的問題是,你在你的兩個using塊範圍內調用Arbiter.Activate。不要忘記,您創建的CCR任務正在排隊,當前線程繼續......正好超出using塊的範圍。您已經創建了一個競爭條件,因爲Choice必須在connSPcmdSP處置之前執行,並且這隻會在您干擾線程計時時發生,正如您在調試時觀察到的那樣。

如果您要在處理程序代理中手動處理Choice,則不會再出現此問題,但這會使代碼易於忽略處理的脆弱代碼。

我建議實施CCR迭代器模式並用MulitpleItemReceive收集結果,以便您可以保留您的using聲明。它使得代碼更簡潔。關閉我的頭頂,它會是這個樣子:

private IEnumerator<ITask> QueryIterator(
    string command, 
    PortSet<Int32,Exception> resultPort) 
{ 
    using (SqlConnection connSP = 
     new SqlConnection(Settings.Default.nbfConn 
      + ";MultipleActiveResultSets=true;Async=true")) 
    using (SqlCommand cmdSP = new SqlCommand()) 
    { 
     Int32 result = 0; 
     connSP.Open(); 
     cmdSP.Connection = connSP; 
     cmdSP.CommandTimeout = 150; 
     cmdSP.CommandText = "set arithabort on; " + commands[i]; 

     yield return Arbiter.Choice(ApmToCcrAdapters.GetReader(cmdSP), 
      delegate(Int32 reader) { resultPort.Post(reader); }, 
      delegate(Exception e) { resultPort.Post(e); }); 
    } 

} 

,你可以使用它是這樣的:

var resultPort=new PortSet<Int32,Exception>(); 
foreach(var command in commands) 
{ 
    Arbiter.Activate(queue, 
     Arbiter.FromIteratorHandler(()=>QueryIterator(command,resultPort)) 
    ); 
} 
Arbiter.Activate(queue, 
    Arbiter.MultipleItemReceive(
     resultPort, 
     commands.Count(), 
     (results,exceptions)=>{ 
      //everything is done and you've got 2 
      //collections here, results and exceptions 
      //to process as you want 
     } 
    ) 
);