1

我对 Scala 中的标准 actor 库的理解存在问题。在下面的代码中,我创建了一个简单的 swing,它基本上应该测试它是否能够连接到 postgreSQL 服务器。然而,它并没有那么远,我使用 Actors 因为 UI 会在执行连接到数据库所需的工作时冻结。当我使用这条线时(意味着我使用演员而不是单个线程)

PostgresCheck ! new GetInfo()

Swing 永远不会更新。但是,如果我将该行注释掉并使用接下来的三行。(意思是演员不会被使用)

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

Swing 将冻结,但大约 25 秒后,Swing 将更新。

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"
}
4

2 回答 2

2

看来,您是在演员之外发送消息。试试这个:

Actor.actor { PostgresCheck ! new GetInfo() }

不确定它是否会有所帮助,但这是标准建议。

而且,现在我想起来了,答案将发送给谁?您正在回复不存在的发件人。我想你想得到答案guiActor,但我不认为你这样做。

于 2010-02-18T02:13:30.407 回答
1

好的,我们开始,问题与线路有关

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")

更改上述行时,代码按预期运行。

于 2010-02-18T09:47:16.453 回答