2011-04-30 60 views
5

嗨 我正在使用scala(2.8.1)來實現使用actor的耗時任務處理程序,但是,我無法在運行我的單元測試時清除它,所以我的單元測試永遠掛起。如何在斯卡拉清理我的死亡演員

我如何調用該方法是:

val configs = new ProjectsConfig("XXXXXXXXXXXXX") 
    try { 
    configs.start 
    configs.init//time consuming stuff 
    } finally { 
    configs.destory 
    configs.stop 
    } 

我打算做的是保持演員的參考,並呼籲各退出,代碼片段是這樣的:

  • init,初始化演員並保留每個演員的參考。
  • 破壞,每個演員呼叫退出。
  • 停止,呼叫此演員退出。

但是,它似乎工作不正常。在這種情況下如何清理所有參與者?

class ProjectsConfig(val url: String) extends Actor { 
    private var actors: List[Actor] = List() 
    private object Stop 

    def init = { 
    val caller = this; 
    for (projectConfig <- list) { 
     val myActor: Actor = actor { 
     caller ! projectConfig.instantiate 
     } 
     actors = actors ::: List(myActor) 
    } 
    } 

    def act() { 
    while (true) { 
     receive { 
     case project: Project => 
      Projects.update(project) 
     case Stop => exit() 
     } 
    } 
    } 

    def destory { 
    for (actor <- actors) { 
     try { 
     actor ! exit 
     } catch { 
     case e => System.out.println(e.printStackTrace) 
     } 
    } 
    } 

    def stop() { 
    this ! Stop 
    } 

回答

3

1)在你的具體情況,我將簡化

val myActor: Actor = actor { 
caller ! projectConfig.instantiate 
} 

只是caller ! projectConfig.instantiate。您已經從演員的子系統撥打電話,因此不需要額外的包裝。

除此之外,雖然它通常建議調用從演員的環境行爲(產卵通話),它不是一個‘必須’在所有(沒有邪惡會發生,如果你直接在調用actor非演員env)。在你的情況下,包裝的調用,而不是增加了問題(樣板和不一致)。

2)actor ! exit實際發生的事情是actor ! Actor.exitassuming that you have a wildcard import on Actor)。此代碼會拋出一個異常,試圖評估Actor.exit,並且沒有任何內容會發送給actor。爲了阻止演員,您必須在其實例上調用exit。它可以通過消息發送來完成,這將稱爲受保護的exit

actor{ 
    loop{ 
    react{ 
     case `exit => exit('stop) 
    } 
    } 
}