Scala Actors неожиданно приостанавливается при подключении к базе данных - PullRequest
1 голос
/ 18 февраля 2010

У меня проблема с пониманием стандартной библиотеки актеров в Scala. В приведенном ниже коде я создал простой свинг, который должен проверять, может ли он подключиться к серверу postgreSQL. Однако это не делает это так далеко, я использую Actors, поскольку пользовательский интерфейс иначе завис бы при выполнении работы, необходимой для подключения к базе данных. Когда я использую эту строку (это означает, что я использую актеры вместо одного потока)

PostgresCheck ! new GetInfo()

Качели никогда не будут обновлены. Однако, если я закомментирую строку и буду использовать следующие три строки. (имеется в виду, что актеры не будут использованы)

      val result = PostgresCheck.checkPostgreSQL
      if (result == "OK") pgText.background = GREEN else pgText.background = RED
      pgText.text = result

Свинг замерзнет, ​​но примерно через 25 секунд свинг будет обновлен.

import dbc.Database
import dbc.vendor.PostgreSQL
import java.awt.Dimension
import java.net.URI
import java.sql.Connection
import swing.event._
import swing._
import actors.Actor
import java.awt.Color._
import scala.actors.Actor._

case class Info(reply: String)
case class GetInfo()

object Example extends SimpleSwingApplication {
  val pgButton = new Button("Check PostgreSQL")
  val pgText = new TextArea("Not Checked Yet")
  val pgPanel = new GridPanel(1, 2)
  pgPanel.contents += pgButton
  pgPanel.contents += pgText

  def top = new MainFrame {
    title = "StateChecker"
    contents = pgPanel
  }

  listenTo(pgButton)
  reactions += {
    case e: ButtonClicked if (e.source.eq(pgButton)) => {
      PostgresCheck ! new GetInfo()

      //val result = PostgresCheck.checkPostgreSQL
      //if (result == "OK") pgText.background = GREEN else pgText.background = RED
      //pgText.text = result
    }
  }

  val guiActor = new Actor {
    def act() = {
      loop {
        react {
          case e: String => {
            val result = e
            if (result == "OK") pgText.background = GREEN else pgText.background = RED
            pgText.text = result
          }
          case e => println(e.toString)
        }
      }
    }
  }
  guiActor.start
}

object PostgresCheck extends Actor {
  def checkPostgreSQL() = {
    try {
      val db = new Database(myPgSQL)
      val con: Connection = myPgSQL.getConnection // Freezes while doing this method
      val statement = con.createStatement
      if (statement.getResultSet.getMetaData.getColumnCount == 1) "OK"
      else statement.getWarnings.toString
    }
    catch {
      case e => e.toString
    }
  }

  def act() = {
    loop {
      react {
        case e: GetInfo => {
          sender ! new Info(checkPostgreSQL)
        }
      }
    }
  }
  start()
}

object myPgSQL extends PostgreSQL {
  val uri = new URI("jdbc:postgresql://whatever.com")
  val user = "1234"
  val pass = "1234"
}

Ответы [ 2 ]

2 голосов
/ 18 февраля 2010

Кажется, вы отправляете сообщение за пределами актера. Попробуйте это:

Actor.actor { PostgresCheck ! new GetInfo() }

Не уверен, поможет ли это, но это стандартный совет.

И теперь, когда я думаю об этом, кому будет отправлен ответ? Вы отвечаете несуществующему отправителю. Я полагаю, вы хотите получить ответ на вопрос guiActor, но я не вижу, чтобы вы это делали.

1 голос
/ 18 февраля 2010

Хорошо, мы идем, проблема была связана со строкой

sender ! new Info(checkPostgreSQL)

На самом деле это должно было быть

Example.guiActor! new Info(checkPostgreSQL)

По какой-то причине, связанной с библиотекой Actor, она фактически приостанавливается при ожидании соединения с базой данных и не возвращается из-за неизвестного отправителя. Например, следующие строки приводят к распечатке только одной строки в консоли с «1».

      val db = new Database(myPgSQL)
      println("1")
      // Freezes while doing this method
      val con: Connection = myPgSQL.getConnection 
      println("2")

При изменении указанной строки код ведет себя как ожидалось.

...