0

「ステップ」メソッドと「タイマー」としての他のメソッドを持つ Myclass という名前のクラスがあります。以下は、両方の方法のコードです。「initialize」メソッドはステッピングを開始します。目的は、ステッピングにかかった時間 (ミリ秒単位) を計算することです。

Myclass>> step  
self bounds: ((self bounds)  expandBy:1).
[(self extent )> (200@200) ifTrue:[self stopStepping.
                     tend:= Time millisecondClockValue.
                     result:= (tend-tstart).
                     Transcript cr; show: 'Semaphore signaled'.
                    sem signal. ]] fork.

Myclass>>timer
tstart:=Time millisecondClockValue.
[sem:= Semaphor new.
 sem wait.
 Transcript show: result.
 "^ result"] fork.

上記のコードは正常に動作していますが、結果の値を返そうとすると、ブロックが返せないというエラーが表示されます。結果が更新されるまでプロセスを待機させ、結果の値を取得することは可能ですか?

4

2 に答える 2

1

フレームレート

最後に足を踏み入れてからかかった時間を知りたい場合は、 を参照してFrameRateMorphください。これは、モーフのメソッドで計算される2 つのインスタンス変数 と を保持しますlastDisplayTimeframesSinceLastDisplay#step

FrameRateMorph>>#step
"Compute and display (every half second or so) the current framerate"

| now mSecs mSecsPerFrame framesPerSec newContents |
framesSinceLastDisplay := framesSinceLastDisplay + 1.
now := Time millisecondClockValue.
mSecs := now - lastDisplayTime.
(mSecs > 500 or: [mSecs < 0 "clock wrap-around"]) ifTrue: 
    [mSecsPerFrame := mSecs // framesSinceLastDisplay.
    framesPerSec := (framesSinceLastDisplay * 1000) // mSecs.
    "…"
    lastDisplayTime := now.
    framesSinceLastDisplay := 0]

モーフで同様のロジックを使用できます。

できるだけ頻繁に呼び出されるように returnをFrameRateMorph実装することに注意してください。この数値に応じて計算を調整する必要がある場合があります。#stepTime0

プロセスの同期

上記の方法で目標を達成できない場合、3 つの選択肢があります。

ブロック/フォークを省略

のフォークが本当に必要#timerですか? これはどうですか:

Myclass>>#timer
    tstart:=Time millisecondClockValue.
    sem:= Semaphor new.
    sem wait.
    Transcript show: result.
    ^ result

これは、結果が準備できるまでブロックされます。

フォークして待つ

フォークされたブロックの使用を主張する場合は、次のことを検討して#forkAndWaitください。

Myclass>>#timer
    tstart:=Time millisecondClockValue.
    [sem:= Semaphor new.
    sem wait.
    Transcript show: result] forkAndWait.
    ^ result

これも、結果が準備できるまでブロックされます。

コールバックする

結果の準備ができたら、積極的にコードを呼び出すことができます

引数によるコールバック

one-argument-block を変更されたタイマー関数に渡し、結果を操作します。

Myclass>>#timerDo: aBlock
    tstart:=Time millisecondClockValue.
    [sem:= Semaphor new.
    sem wait.
    Transcript show: result.
    aBlock value: result] fork.

その後

| obj |
" assume that obj is an instance of Myclass"
obj timerDo: [:result |
    "do something meaningful with the result, eg, show it "
    blaObject showResult: result.].

インスタンス変数によるコールバック ブロック

callBackインスタンス変数を追加しますMyclass#timer

Myclass>>#timer
    tstart:=Time millisecondClockValue.
    [sem:= Semaphor new.
    sem wait.
    Transcript show: result.
    callBack value: result] fork.

そしてそれを次のように使用します

| obj |
" assume that obj is an instance of Myclass"
obj callBack: [:result |
    "do something meaningful with the result, eg, show it "
    blaObject showResult: result.].
obj timer.

メッセージ送信によるコールバック

これは危険であり、あなたが求めているものではないことに注意してください

3 番目のオプションは、ブロックをコールバックとして保存するのではなく、結果の到着時にオブジェクトに直接メッセージを送信することです。

target2 つのインスタンス変数を追加selectorMyclassます#timer

Myclass>>#timer
    tstart:=Time millisecondClockValue.
    [sem:= Semaphor new.
    sem wait.
    Transcript show: result.
    target perform: selector with: result] fork.

そしてそれを次のように使用します

| obj |
" assume that obj is an instance of Myclass"
obj
    target: blaObject;
    selector: #showResult: .
obj timer.

ただし、すべてのプロセスの同期では、さまざまな種類のトラブルが発生する可能性があるため、可能であれば最初のオプションを最初に試してください。

于 2013-09-12T17:38:43.643 に答える