我正在尝试使用https://github.com/klkblake/Go-SDL编写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 mainimport ("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 }}
2 回答
一只名叫tom的猫
TA贡献1906条经验 获得超3个赞
请参阅golang:带有select的goroute不会停止,除非我添加了fmt.Print()
长话短说,由于使用默认情况,并且因为您的GOMAXPROCS可能设置为1(默认值),所以它永远不会安排goroutine进行工作。根据您的需要,有很多选项可以解决此问题(默认情况下为sleep,select中的time.After()通道而不是默认通道,对runtime.Gosched()的调用等)。
添加fmt.Print使其能够工作是因为-我的猜测(不确定)-它涉及io并在内部导致Gosched()(在相关问题中类似于Phlip的答案,我只是读过它)。
白衣染霜花
TA贡献1796条经验 获得超10个赞
就您的示例而言,您的循环是一个繁忙的循环,不断遇到麻烦default:
。go中的调度程序是协作的,并且由于您处于繁忙的循环中,因此运行Ticker的go例程将永远不会被调度运行,因此永远不会在通道上发送任何内容。即使您的default:
情况不为空,而是进行纯计算-绝不会进行任何调用schudler的调用,情况就是如此。
但是,当您执行某种以某种形式调用go调度程序的操作(例如,执行I / O时),调度程序将为代码行提供运行的机会。
您可以导入运行时包并执行
default: runtime.Gosched()
使调度程序运行,这不会使Ticker go例程陷入饥饿。
我不确定这将如何导致您在运行SDL时遇到的问题,因为这很可能涉及I / O或其他触发调度程序的问题
- 2 回答
- 0 关注
- 184 浏览
添加回答
举报
0/150
提交
取消