1

Scalaの標準アクターライブラリの理解に問題があります。以下のコードでは、単純なスイングを作成しました。これは基本的に、postgreSQLサーバーに接続できるかどうかをテストする必要があります。ただし、それほど遠くはありません。データベースへの接続に必要な作業を実行しているときにUIがフリーズするため、アクターを使用します。この行を使用する場合(つまり、単一のスレッドではなくアクターを使用します)

PostgresCheck ! new GetInfo()

Swingは更新されません。ただし、その行をコメントアウトして、次の3行を使用するとします。(アクターが使用されないことを意味します)

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

アクター ライブラリに関連する何らかの理由で、データベース接続を待機しているときに実際にサスペンドし、不明な送信者のために戻りません。たとえば、次の行では、コンソールに "1" の 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 に答える