简体   繁体   English

由于频繁重绘C#Windows表单自定义控件,如何减少高CPU使用率?

[英]How do I reduce high CPU usage because of a C# Windows forms custom control being redrawn frequently?

Ogmo Editor is a nice open source 2D map editor written in C# which unfortunately has a high CPU usage problem - whenever you open the actual level editing screen it completely saturates a single CPU core. Ogmo Editor是使用C#编写的一个不错的开源2D地图编辑器,不幸的是它具有很高的CPU使用率问题-每当您打开实际的关卡编辑屏幕时,它就会完全饱和单个CPU内核。 I looked into the source and after profiling it came to the conclusion that the OnPaint handler of the LevelEditor custom control is being called repeatedly. 我查看了源代码,并进行了分析,得出的结论是, LevelEditor自定义控件OnPaint处理程序被重复调用。 I am not very familiar with the Windows Forms API and checked the MSDN documentation about custom controls but was unable to determine the source of the problem. 我对Windows Forms API不太熟悉,并查看了有关自定义控件的MSDN文档 ,但无法确定问题的根源。

I then looked into another similar open source project called tIDE which to me seems to be rendering its editing screen - the MapPanel control in a very similar manner - please see the OnMapPaint() function definition in the link for details. 然后,我查看了另一个名为tIDE的类似开源项目,对我来说,它似乎正在渲染其编辑屏幕-MapPanel控件以一种非常相似的方式-有关详细信息,请参见链接中的OnMapPaint()函数定义。

I am not sure why the control should refresh when it is not changing, I think someone familiar with the API may be able to suggest a solution. 我不确定控件为什么在不更改时应该刷新,我认为熟悉API的人也许可以提出解决方案。

Try this. 尝试这个。 Derive your own CustomLevelEditor from OgmoEditor.LevelEditors.LevelEditor . 派生自己CustomLevelEditorOgmoEditor.LevelEditors.LevelEditor Then override the OnPaint event like this. 然后像这样重写OnPaint事件。

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

Sleeping for 1ms in the UI thread between paint events will bring the CPU cycles down significantly. 在两次绘画事件之间的UI线程中睡眠1毫秒将大大降低CPU周期。 If OnPaint gets fired by the base control non-stop, then you might try something like this. 如果OnPaint不停地被基本控件触发,那么您可以尝试这样的操作。

    int paintReps = 0;

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

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

I hope this helps. 我希望这有帮助。 Take care. 照顾自己。

The problem was the following code in the level editor file : 问题是关卡编辑器文件中的以下代码:

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

The Application Idle event occurs just before the application is about to become idle and this resulted in an infinite redraw loop which is very processor intensive. Application Idle事件恰好在应用程序即将变得空闲之前发生,这导致了无限的重绘循环,这会占用大量处理器。 Removing the Invalidate() call required updating the code to redraw whenever a user interaction occurs, this required changes to multiple files in the project and the resulting commit can be seen here on Bitbucket . 删除Invalidate()调用需要更新代码,以便每当发生用户交互时都可以重绘,这需要更改项目中的多个文件,并且可以在Bitbucket上看到生成的提交。

For anyone else having similar issues the problem of excessive redraws is likely to be caused because of changes to the control or manual Invalidate() calls. 对于其他有类似问题的人,可能由于控件或手动Invalidate()调用的更改而导致重绘过多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM