2010-02-17 18 views
1

我对我对Scala中的标准演员库的理解有问题。在下面的代码中,我创建了一个简单的swing,它基本上应该测试它是否能够连接到postgreSQL服务器。然而它并没有达到那样的程度,我使用了Actor,因为UI在完成连接数据库所需的工作时会冻结。 当呃我使用这条线(意思是我用的演员,而不是一个单独的线程)Scala Actor连接到数据库时会暂停意外

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" 
} 
+0

你可以在应用程序挂起时转储堆栈跟踪吗?在窗口上,在控制台窗口中,在Unix上CTRL-BREAK,'kill -QUIT pid',其中pid是进程ID。 – retronym

+0

在标准tty设置下,CTRL- \将在Unix和Linux下生成一个QUIT信号。 –

+0

您确定PostgresCheck的初始化程序甚至正在运行吗? (也就是说,如果你在'start()'之后放了一个'println(“Running”)',你看到它了吗?)你是否曾经将它放入guiActor的反应声明中? –

回答

2

你正在一个演员之外发送消息,看来。试试这个:

Actor.actor { PostgresCheck ! new GetInfo() } 

不知道它是否会有所帮助,但它是标准的建议。

而现在我想起来了,答案会发给谁?您正在回复不存在的发件人。我想你想要的答案是guiActor,但我没有看到你这样做。

+0

如果我使用建议的方式,我没有什么不同。 GUI Event线程只是创建一条消息并将其放入队列中,所以它不应该有任何区别。 不错的地方,我没有注意到,我把答复发送到错误的地方,'发件人'应该替换为'Example.guiActor'。 – Stefan

1

好我们开始吧,这个问题是涉及到线

sender ! new Info(checkPostgreSQL) 

它实际上应该已经

Example.guiActor! new Info(checkPostgreSQL) 

对于相关的演员库因故等待的时候,它实际上暂停数据库连接,并且不会因为未知的发件人而返回。例如,以下行可以打印出控制台中只有一行的“1”。

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

更改提到的行时,代码的行为与预期相同。