AS3中的竞赛条件触发事件

时间:2009-12-02 17:30:57

标签: flash actionscript-3 events race-condition

我在按正确的编年史顺序解雇和删除事件时遇到了一些麻烦。下面的代码给出了以下输出:

  • 将海报保存到数据库中,并发送事件
  • 调用服务,调度事件已删除= false
  • 调用服务,调度事件已删除= false
  • 调用服务,调度事件已删除= true
  • 将海报保存到数据库中,并发送事件
  • 将海报保存到数据库中,并发送事件

当然这应该更像是:

  • 将海报保存到数据库中,并发送事件
  • 调用服务,调度事件已删除= true
  • 将海报保存到数据库中,并发送事件
  • 调用服务,调度事件已删除= true
  • 将海报保存到数据库中,并发送事件
  • 调用服务,调度事件已删除= true

有人可以帮我吗?我对如何解决这个问题的想法不足。

THX!

    for(var i:int = 0;i< 3;i++){
        createPoster();         
    }

    function createPoster(){
        Main.db.savePoster();
        Main.db.addEventListener(Config.evt_SAVEPOSTER_READY, callService);
    }

    function callService(){
       Main.db.removeEventListener(Config.evt_SAVEPOSTER_READY, callService);
    }

3 个答案:

答案 0 :(得分:1)

问题是您在单个callService对象Config.evt_SAVEPOSTER_READY上为同一事件EvenDispatcher注册了相同的功能db。因此,一旦savePoster成功保存海报后第一次调度事件,db就会收到该事件,并调用三个eventHandler(在本例中为callService),因为callService已注册三次。因此,一种解决方案是从海报发送事件。

for(var i:int = 0;i< 3;i++){
  createPoster();
}
function createPoster(){
  poster = Main.db.savePoster();
  poster.addEventListener(Config.evt_SAVEPOSTER_READY, callService);
}
function callService(e:PosterEvent){
  e.target.removeEventListener(Config.evt_SAVEPOSTER_READY, callService);
}

答案 1 :(得分:0)

您是否检查了仅循环浏览一个项目时会发生什么?在我看来,你并没有正确排队。

您可能只想将一个事件监听器添加到Main.db对象一次,并在成功保存所有“海报”后将其删除。

答案 2 :(得分:0)

db调用(Main.db.savePoster();)是否同步 - 仅在操作完成后才返回?由于您在db调用之后调用addEventListener,因此如果db-call是同步的,则不会调用事件侦听器(至少第一次迭代)。

Main.db在所有三次迭代中是否都是相同的实例?如果是,您不必为它注册相同的事件监听器三次 - 一次就足够了。在启动for循环之前调用addEventListener。保留一个计数器,用于跟踪callService的调用次数,并在计数器达到循环计数后调用removeEventListener(在本例中为3)。