2012-10-14 72 views
4

我正在嘗試使用https://github.com/klkblake/Go-SDL編寫SDL應用程序。
我創建的計時器來調用它繪製函數:選擇的奇怪行爲(不允許其他goroutines運行)

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") 
默認分支

選擇 - 代碼開始工作,我希望它(畫東西的窗口);如果我刪除println它再次不繪製任何東西。
我在做什麼錯?爲什麼有這樣的行爲選擇


唔...最簡單的測試用例是:

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

回答

6

golang: goroute with select doesn't stop unless I added a fmt.Print()

長話短說O或別的東西,由於默認情況,並且因爲您的GOMAXPROCS可能設置爲1(默認值),所以它永遠不會調度goroutine來完成它的工作。有很多選項可以解決這個問題,這取決於你的需求(默認睡眠,time.After()通道,而不是默認值,調用runtime.Gosched()等)。

添加fmt.Print使其工作是因爲 - 我的猜測,不確定 - 它涉及io並在內部導致Gosched()(或者類似於Phlip在相關問題中的答案,我只是閱讀它)。

7

至於你的榜樣,你的循環是一個繁忙的循環,不斷衝擊的情況下default:。進程中的調度程序是合作的,並且由於您處於繁忙的循環中,運行定時器的去程序永遠不會計劃運行,因此從不在通道上發送任何內容。即使您的default:案件不是空的,也會出現這種情況,但要進行純粹的計算 - 從不發出任何調用schudler的調用。

但是,當您執行某些其他形式的調用go scheduler的其他內容時,例如,做I/O,調度程序會給Ticker一個運行的機會。

你可以導入運行時包,並做

default: 
    runtime.Gosched() 

,使調度運行,不會餓死北京時間走程序。

我不能確定這是如何導致運行SDL當你的問題,因爲這將很可能會涉及I /觸發調度