如何通过重新绘制C#Windows窗体自定义控件来减少高CPU使用率?

时间:2014-01-17 03:34:00

标签: c# .net winforms graphics gdi+

Ogmo Editor是一个很好的开源2D地图编辑器,用C#编写,遗憾的是它具有很高的CPU使用率问题 - 每当你打开实际的关卡编辑屏幕时,它就会使单个CPU内核完全饱和。我查看了source,在对其进行分析后得出结论:OnPaint handlerLevelEditor custom control被重复调用。我对Windows Forms API不是很熟悉,并检查了MSDN documentation有关自定义控件但无法确定问题的根源。

然后我查看另一个名为tIDE的类似开源项目,对我来说似乎是以非常类似的方式呈现其编辑屏幕MapPanel control - 请参阅OnMapPaint()函数定义链接了解详情。

我不确定为什么控件在不改变时应该刷新,我认为熟悉API的人可能会建议解决方案。

2 个答案:

答案 0 :(得分:1)

试试这个。从CustomLevelEditor获取您自己的OgmoEditor.LevelEditors.LevelEditor。然后像这样覆盖OnPaint事件。

    protected override void OnPaint(PaintEventArgs e) {
        base.OnPaint(e);
        System.Threading.Thread.Sleep(1);
    }

在绘制事件之间的UI线程中休眠1ms将显着降低CPU周期。如果基本控件不停地触发OnPaint,那么您可以尝试这样的事情。

    int paintReps = 0;

    protected override void OnPaint(PaintEventArgs e) {
        base.OnPaint(e);
        System.Threading.Thread.Sleep(1);

        if(paintReps++ % 500 == 0)
            Application.DoEvents();
    }

我希望这会有所帮助。小心。

答案 1 :(得分:0)

问题是level editor file中的以下代码:

 void Application_Idle(object sender, EventArgs e)
 {
      Invalidate();
      LevelView.Update();
 }

Application Idle事件恰好在应用程序即将变为空闲之前发生,这导致无限重绘循环,这是非常耗费处理器的。删除Invalidate()调用需要更新代码以便在用户交互发生时重绘,这需要更改项目中的多个文件,并且可以看到生成的提交here on Bitbucket

对于其他有类似问题的人来说,由于控件或手动Invalidate()调用的更改,可能会导致过度重绘的问题。