3

becomeAkka アクターでの使用に問題があります。基本的に、私のアクターは次のような構造になっています。

// This is where I store information received by the actor
// In my real application it has more fields, though.
case class Information(list:List[AnyRef]) {
    def received(x:AnyRef) = {
        Information(list :+ x)
    }
}

class MyActor extends Actor {

    // Initial receive block that simply waits for a "start" signal
    def receive = {
        case Start => {
            become(waiting(Information(List())))
        }
    } 

    // The main waiting state. In my real application, I have multiple of
    // these which all have a parameter of type "Information"
    def waiting(info:Information):Receive = {

        // If a certain amount of messages was received, I decide what action
        // to take next.
        if(someCondition) {
            decideNextState(x)
        }

        return {
            case Bar(x) => {
                //
                // !!! Problem occurs here !!!
                //
                // This is where the problem occurs, apparently. After a decision has been
                // made, (i.e. decideNextState was invoked), the info list should've been
                // cleared. But when I check the size of the info list here, after a decision
                // has been made, it appears to still contain all the messages received
                // earlier.
                //
                become(waiting(info received x))
            }
        }
    }

    def decideNextState(info:Information) {
        // Some logic, then the received information list is cleared and 
        // we enter a new state.
        become(waiting((Information(List())))
    }
}

長いコード スニペットで申し訳ありませんが、これ以上小さくすることはできませんでした。

問題が発生する部分はコメントでマークされています。Receiveメソッドに渡される部分関数を返​​すパラメーターをメソッドに渡していますbecome。ただし、作成された部分関数は、以前の呼び出しから何らかの形で状態を保持しているようです。問題を説明するのは少し難しいと思いますが、コード内のコメントで説明するために最善を尽くしたので、それらを読んでください。不明な点はすべて回答します。

4

1 に答える 1

3

あなたの論理は少し複雑ですが、何が問題なのかを見ていきます。

が true の場合someCondition、アクターは状態に入ります。値 Information(List()) によって特徴付けられる S1 と呼びましょう。そして、returnアクターをリスト Information(somePreviousList :+ x) で特徴付けられる状態 S2 にする receive メソッドを返します (ちなみに、どうしても必要な場合を除き、使用は避けてください)。したがって、この時点で、状態のスタックの一番上に S1 があります。しかし、Bar(x)メッセージを受信すると、状態 S2 がプッシュされるため、S1 がカバーされ、実際には、古い値 + 新しい を持つ情報によって特徴付けられる状態に遷移しますx

またはそのようなものですが、あなたのアクターの再帰は少し魅力的です。

しかし、変更される状態は情報型のものであり、Akka のアクター状態遷移を使用してこの状態を操作しているように見えるため、そのコードを書き直すことをお勧めします。これは、それを行うための最良のツールではありません。アクターの動作のさまざまな状態から遷移するために使用することを意図していbecomeます。つまり、アクターはいつでも異なる動作をすることができ、これらの動作を切り替えるにはとを使用します。unbecomebecomeunbecome

このようなことをしてみませんか?

class MyActor extends Actor {

    private var info = Information(List.empty)

    def receive = {
        case Start => info = Information(List()) //a bit redundant, but it's just to match 1:1 with your code
        case Bar(x) => {
            if (someCondition) {
                info = Information(List.empty)
            }
            info = info received x
        }
    }

}

私はあなたのアイデア全体を把握できていないかもしれませんが、全体像は理解できました。

于 2012-11-15T16:46:45.727 に答える