4

https://github.com/klkblake/Go-SDLを使用してgoでSDLアプリを作成しようとしています。
描画関数を呼び出すタイマーを作成しました。

render_timer := time.NewTicker(time.Second / 60)

イベントループのどこか:

for running == true {
    [...]
    [process sdl events]
    [...]
    select {
    case <-render_timer.C:
        call_my_draw_function()
    default:
        some_default_actions()
    }
    [...]
}

このコードをコンパイルした後にプログラムを実行すると、画面に何も表示されません。しかし、私がちょうど置くならば:

fmt.Println("default")

selectデフォルトのブランチで-コードは私が望むように動作し始めます(ウィンドウに何かを描画します); printlnを削除しても、何も描画されません。 私は何が間違っているのですか?なぜそのようなselectの動作があるのですか?


うーん...最も単純なテストケースは次のとおりです。

package main

import (
"fmt"
"time"
)

func main() {

    rt := time.NewTicker(time.Second / 60)
    for {
        select {
        case <-rt.C:
            fmt.Println("time")
        default:
        }
    time.Sleep(1) // without this line 'case <-rt.C' is never executed
    }
}
4

2 に答える 2

8

あなたの例のように、あなたのループはビジーループであり、常にdefault:ケースにぶつかっています。goのスケジューラーは協調的であり、ビジーループになっているため、Tickerを実行するgoルーチンの実行がスケジュールされることはなく、チャネルで何も送信されません。これは、default:ケースが空でない場合でも当てはまりますが、純粋な計算を実行します。これにより、シュドラーを呼び出す呼び出しは行われません。

ただし、I / Oを実行するなど、何らかの形でgoスケジューラーを呼び出す何かを実行すると、スケジューラーはTickerに実行の機会を与えます。

ランタイムパッケージをインポートして実行できます

default:
    runtime.Gosched()

スケジューラーを実行します。これにより、ティッカーゴールーチンが不足することはありません。

これがSDLの実行時に発生する問題にどのようにつながるかはわかりません。これは、I/Oまたはスケジューラーをトリガーする他の何かが関係している可能性が高いためです。

于 2012-10-14T18:50:14.157 に答える
6

golangを参照してください:fmt.Print()を追加しない限り、selectを使用したgorouteは停止しません

簡単に言うと、デフォルトの場合と、GOMAXPROCSがおそらく1(デフォルト値)に設定されているため、ゴルーチンがその作業を実行するようにスケジュールすることはありません。必要に応じて、これを修正するための多くのオプションがあります(デフォルトでのスリープ、デフォルトではなくselectのtime.After()チャネル、runtime.Gosched()の呼び出しなど)。

fmt.Printを追加すると、それが機能するようになります。これは、(私の推測ではありませんが)ioが関与し、内部的にGosched()を引き起こすためです(これは、関連する質問でのPhlipの回答のようなものです。私はそれを読んだだけです)。

于 2012-10-14T18:51:57.413 に答える