2011-11-24 66 views
1

我有如下獲取處方清單查詢:Silverlight的異步操作的foreach循環

var PRSCRPTSQuery = GV.dbContext.Load(GV.dbContext.GetPRSCRPTQuery(GV.curCustomer.CustCode, 
              oOrdritemEdited.ProdCode, oOrdritemEdited.MedCode)); 
       PRSCRPTSQuery.Completed += new EventHandler(PRSCRPTSQuery_Completed); 

在查詢完成的事件,我有以下代碼:

void PRSCRPTSQuery_Completed(object sender, EventArgs e) 
    {   
     lstPRSCRPT = GV.dbContext.PRSCRPTs.Where(p=>p.Status =="Activated").ToList(); 
     if (lstPRSCRPT.Count > 0) 
     { 
      foreach (var rec in lstPRSCRPT) 
      { 
       var OrderItemQuery = GV.dbContext.Load(GV.dbContext.GetOrdritemsQuery(rec.PresNo)); 
       OrderItemQuery.Completed += new EventHandler(OrderItemQuery_Completed);    
      }        
     } 
    }  

名單lstPRSCRPT可以包含多條記錄。我相信,foreach循環將提前在循環的下一個項目,而不必等待OrderItemQuery_Completed事件,低於:

void OrderItemQuery_Completed(object sender, EventArgs e) 
    { 
     lstOrderItem = GV.dbContext.OrderItems.ToList(); 
     if (lstOrderItem.Count > 0) 
     { 
      foreach (var OrdrItemRec in lstOrderItem) 
      { 
       TotTonnes = (double)(TotTonnes + OrdrItemRec.Quantity); 
      }    
     } 
    } 

是否有任何變通解決辦法這種情況呢?我是新來的異步編程類型在SL

+0

您在尋找什麼解決方法?至於爲什麼目前遇到問題呢?你是正確的,因爲for循環將不會等待,並會循環發送儘可能多的請求(假設你省略了執行代碼行) – Chris

+0

我的擔心是如何知道我什麼時候可以執行某些代碼在所有回電完成後。 – sony

回答

1

我看到你從哪裏來,當我第一次啓動Silverlight編程我抓住了我的同步執行的先入爲主,所以我知道我什麼時候完成調用查詢,我也知道我在哪裏它是錯誤的。然而

的Silverlight採用這一概念,並試圖從吼你撕「這種方式是更好的相信我!」並且爲了增強客戶端交互性,它肯定會成功。這只是需要時間。你只需要更多地瞭解如何將它們連接在一起的風格。

以前更快的解決方案中顯示的鏈接顯示了C#中的異步編碼方面去,但它支付給知道它的實際完成你。其中一些您已經在問題中鏈接的代碼中掌握了。

當我面對你有相同的情況下,你必須背靠背異步回調是提高時,我已經做完我在做什麼的事件。例如:

public event EventHandler<EventArgs> LoadComplete; 
public int QueryCount {get;set;} 
public int QuerysCompleted {get;set;} 

public void GetItems() 
{ 
    var PRSCRPTSQuery = GV.dbContext.Load(GV.dbContext.GetPRSCRPTQuery 
     (GV.curCustomer.CustCode, oOrdritemEdited.ProdCode, oOrdritemEdited.MedCode)); 
    PRSCRPTSQuery.Completed += new EventHandler(PRSCRPTSQuery_Completed); 
    LoadComplete += loader_LoadComplete; 
} 


void PRSCRPTSQuery_Completed(object sender, EventArgs e) 
{   
    lstPRSCRPT = GV.dbContext.PRSCRPTs.Where(p=>p.Status =="Activated").ToList(); 
    if (lstPRSCRPT.Count > 0) 
    { 
     QueryCount = lstPRSCRPT.Count; 
     foreach (var rec in lstPRSCRPT) 
     { 
      var OrderItemQuery = GV.dbContext.Load(GV.dbContext.GetOrdritemsQuery(rec.PresNo)); 
      OrderItemQuery.Completed += new EventHandler(OrderItemQuery_Completed);    
     }        
    } 

} 

    void OrderItemQuery_Completed(object sender, EventArgs e) 
    { 
     QueryCompleted++; 
     lstOrderItem = GV.dbContext.OrderItems.ToList(); 
     if (lstOrderItem.Count > 0) 
     { 
      foreach (var OrdrItemRec in lstOrderItem) 
      { 
       TotTonnes = (double)(TotTonnes + OrdrItemRec.Quantity); 
      }    
     } 

    if(QueryCompleted == QueryCount) 
    { 
     RaiseLoadComplete(); 
    } 
    } 



public void RaiseLoadComplete() 
{ 
     if(LoadComplete != null) 
     { 
      LoadComplete(this, new EventArgs()); 
     } 
} 


void loader_LoadComplete(object sender, EventArgs e) 
{ 
     //Code to execute here 
}  

當我完成時,我開始第一個查詢執行什麼代碼時附加一個事件。在第一個查詢回調中,我初始化了我期待的回覆次數。然後在第二個查詢回調中,我增加,直到我得到正確的金額,然後調用事件來說我完成了。

用這種方法唯一的警告是,如果查詢的錯誤之一,最終的代碼將永遠不會得到執行。

+0

嗨克里斯,謝謝你的回答......其實我也在用同樣的方式思考,除了RaiseLoadComplete(); – sony

+0

如果只有一個回調函數,那麼當它完成時將引發一個事件可能會很方便。但是當你有多個依賴異步方法的時候,這是我迄今爲止唯一的方法。但是,我很高興別人認爲沿着同樣的路線=) – Chris

0

您可能會發現感興趣的VS異步CTP。它引入了用於處理異步事件的新「異步」關鍵字。他是一個博客解釋它:VS Async