2011-11-24 106 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