【问题标题】:make GDI drawing more efficient C#让 GDI 绘图更高效 C#
【发布时间】:2015-06-13 16:33:41
【问题描述】:

目前,我的代码占用了我大约 10% 的 CPU 功率。我怎样才能使它更高效,更少闪烁? 代码:

private void timer1_Tick(object sender, EventArgs e)
{
    DrawLocal();
    Thread.Sleep(17);
    pictureBox1.Invalidate();
}

private void DrawLocal()
{
    int localReadX = ReadAddress("hl2", "client.dll+0xBFFF00 364 0");
    int localReadY = ReadAddress("hl2", "client.dll+0xBFFF00 368 0");

    byte[] bytesOflocalX = BitConverter.GetBytes(localReadX);//converts to float
    byte[] bytesOflocalY = BitConverter.GetBytes(localReadY);//converts to float

    float localX = BitConverter.ToSingle(bytesOflocalX, 0)/10;//converts to float
    float localY = BitConverter.ToSingle(bytesOflocalY, 0)/10;//converts to float

    Graphics localP = pictureBox1.CreateGraphics();
    localP.FillRectangle(new SolidBrush(Color.Red), localX, localY, 5, 5);

    Graphics localName = pictureBox1.CreateGraphics();
    localName.DrawString("  local", new Font("Arial", 7), new SolidBrush(Color.Red), localX, localY);
}

【问题讨论】:

  • 由于我们不知道其中 90% 的作用是什么,因此我们无法解释 10%。 ReadAddress 是什么?看起来像内存偏移...您还创建了两次 picturebox1 图形对象,并且您从未处理过它,因此这是内存泄漏(与solidbrushes 相同)。要停止闪烁,您应该进行回缓冲,或者您可以尝试在表单上设置双缓冲选项...另外,为什么您在计时器刻度内有一个Thread.Sleep?它是什么样的计时器?为什么在抽奖后使图片框无效?这会擦除你在其中绘制的内容。计时器的运行频率是多少?
  • 实际上,您永远不应该创建 Graphics,而是使用 Paint 事件的 e.Graphics。只需调用 Invalidate 即可触发它! PictureBox 已经双缓冲了,给它一个工作的机会! Sleeps 在 Timer 中看起来很奇怪,如果你使用 Red 笔刷,请使用 Brushes.Red,不要总是创建相同的字体,将其存储在安全的地方.. 你能估计 ReadAddress 调用的速度有多快或有多慢吗?
  • ReadAddress 读取存储在内存地址 client.dll+.. 中的值。 PictureBox1 是我想在其中绘制矩形和字符串的区域。我叫'pictureBox1.Invalidate();'删除之前在定时器tick中绘制的旧图形(localX和localY的值不时变化)。计时器以 100 毫秒计时。

标签: c# gdi


【解决方案1】:

上面的cmets,演示如下:

    private Font f = new Font("Arial", 7);

    public Form1()
    {
        InitializeComponent();
        pictureBox1.Paint += pictureBox1_Paint;
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        pictureBox1.Invalidate();
    }

    void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        int localReadX = ReadAddress("hl2", "client.dll+0xBFFF00 364 0");
        int localReadY = ReadAddress("hl2", "client.dll+0xBFFF00 368 0");

        byte[] bytesOflocalX = BitConverter.GetBytes(localReadX);//converts to float
        byte[] bytesOflocalY = BitConverter.GetBytes(localReadY);//converts to float

        float localX = BitConverter.ToSingle(bytesOflocalX, 0) / 10;//converts to float
        float localY = BitConverter.ToSingle(bytesOflocalY, 0) / 10;//converts to float

        e.Graphics.FillRectangle(Brushes.Red, localX, localY, 5, 5);
        e.Graphics.DrawString("  local", f, Brushes.Red, localX, localY);
    }

【讨论】:

  • 如果您想减少 CPU 使用率,请减少重绘频率。 “计时器以 100 毫秒计时。”尝试将 100 增加到 250,看看这会改变您的使用情况。顺便说一句,根据其拥有的内核数量,各种系统的 CPU 使用率将有很大不同。例如,i7 核心系统将报告比旧双核心小得多的数字......
  • 或者,您可以只检查localReadX和localReadY是否改变,如果没有,您不需要重新绘制。
  • 那很好。当然,我们不知道在 ReadAddress() 调用中使用了多少百分比的工作。分析工具可能会有所帮助!
  • @Idle_Mind,假设这是他正在使用的ReadAddress 函数 (stackoverflow.com/questions/30694922/…),我敢说那是 99% 的时间,并且可以进行相当多的优化.
猜你喜欢
  • 2013-06-28
  • 2012-09-20
  • 1970-01-01
  • 2011-10-03
  • 2021-08-03
  • 2020-09-12
  • 2018-02-08
  • 2014-03-29
  • 1970-01-01
相关资源
最近更新 更多