как убрать моего мертвого актера в Скале - PullRequest
5 голосов
/ 30 апреля 2011

Привет Я использую scala (2.8.1) для реализации трудоемкого обработчика задач с использованием actor, однако я не могу его очистить при запуске модульных тестов, поэтому мои модульные тесты зависают навсегда.

как я называю метод:

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

То, что я планирую сделать, это сохранить ссылку на актеров и вызывать exit при каждом включении, фрагмент кода выглядит следующим образом:

  • init, инициализировать актеров и сохранить ссылку на каждого актера.
  • destory, вызовите exit для каждого актера.
  • стоп, вызовите выход этого актера.

однако, похоже, это не работает. как убрать всех актеров в этом случае?

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
  }

1 Ответ

3 голосов
/ 30 апреля 2011

1) В вашем конкретном случае я бы упростил

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

до caller ! projectConfig.instantiate.Вы уже делаете вызов из подсистемы актера, поэтому дополнительная упаковка не требуется.

Кроме того, хотя обычно рекомендуется вызывать актеров из среды актеров (порождение вызова), это вовсе не "необходимость" (и никакого зла не случится, если вы вызовете актера непосредственно в env, не являющемся актером).В вашем случае упаковка вызовов скорее добавляет проблем (шаблон и несоответствия).

2) На самом деле в actor ! exit происходит actor ! Actor.exit ( при условии, что в Actor имеется импорт с подстановочными знаками).Этот код вызывает исключение при попытке оценить Actor.exit, и актеру ничего не отправляется.Чтобы остановить актера, вы должны вызвать exit в его экземпляре.Это можно сделать через отправку сообщения, которое вызовет защищенный exit:

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