Отменить все сообщения, кроме последнего, в акторе Scala

У меня есть SwingWorker актер, который вычисляет график для отображения из объекта параметров, который он получает; затем рисует график в ветке EDT. Некоторые элементы графического интерфейса могут изменять параметры этого графика. Когда они меняются, я создаю новый объект параметра и отправляю его работнику.

Пока это работает.

Теперь при перемещении ползунка создается множество событий, которые помещаются в очередь в почтовом ящике работника. Но мне нужно рассчитать график только для самого последнего набора параметров. Есть ли способ удалить все сообщения из почтового ящика; оставить последний и обработать только его?

В настоящее время код выглядит так

val worker = new SwingWorker {
  def act() {
    while (true) {
      receive {
        case params: ExperimentParameters => {
          //somehow expensive
          val result = RunExperiments.generateExperimentData(params)

          Swing.onEDT{ GuiElement.redrawWith(result) }
        }
      }
    }
  }
}

person ziggystar    schedule 06.10.2011    source источник
comment
Можете определить последнюю точнее? Есть ли гарантия, что сообщений больше не будет? Что делать, если до прибытия последнего будет большая задержка? Я думаю, вам нужен (1) тайм-аут или (2) пометить сообщения как not-last / last.   -  person Jus12    schedule 07.10.2011
comment
Я думал, что это ясно из описываемой мной проблемы. Конечно, может быть и больше. Но не следует начинать работу, если после нее уже доступна другая. Потому что это означает, что старый устарел и больше не нужен.   -  person ziggystar    schedule 08.10.2011


Ответы (2)


Тем временем я нашел решение. Вы можете проверить размер почтового ящика актера и просто пропустить сообщение, если он не равен 0.

val worker = new SwingWorker {
  def act() {
    while (true) {
      receive {
        case params: ExperimentParameters => {
          if( mailboxSize == 0) {
            //somehow expensive
            val result = RunExperiments.generateExperimentData(params)
            Swing.onEDT{ GuiElement.redrawWith(result) }
          }
        }
      }
    }
  }
}
person ziggystar    schedule 06.10.2011

Запомните последнее событие, не обрабатывая его, используйте очень короткий тайм-аут, обработайте последнее событие, когда вы получите тайм-аут

может выглядеть (не проверено)

while(true) {
  var lastReceived : Option[ExperimentParameters] = None
  receive {case params : ExperimentParameters => lastReceived = Some(params)}
  while (!lastReceived.isEmpty) {
    receiveWithin(0) {
      case params: ExperimentParameters => lastReceived = Some(params)
      case TIMEOUT => do your job with lastReceived.get;
    }
  }
}
person Didier Dupont    schedule 06.10.2011
comment
Об этом решении тоже думал. У этого есть свойство, что вы можете немного подождать, чтобы собрать больше задач. Хотите ли вы этого, зависит от приложения. - person ziggystar; 06.10.2011