【问题标题】:Windows Form - High CPU usageWindows 窗体 - 高 CPU 使用率
【发布时间】:2018-05-16 02:30:26
【问题描述】:

这里是新手,我的表单正在监视 Caps Lock 状态,但使用了大约 50% 的 CPU,我认为这与 Application.Idle += Application_Idle 和 Application.Idle -= Application_Idle 有关。一旦我删除了那些我的表单没有监控 Caps Lock 状态,有什么建议吗?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CapsLockChecker
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Application.Idle += Application_Idle;
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        void Application_Idle(object sender, EventArgs e)
        {
            if (Control.IsKeyLocked(Keys.CapsLock))
            {
                label1.Text = "CapsLock is On";
                pictureBox1.ImageLocation = "C:\\Users\\user\\source\\repos\\CapsLockChecker\\CapsLockChecker\\if_Circle_Green_34211.png";
            }
            else
            {
                label1.Text = "CapsLock if Off";
                pictureBox1.ImageLocation = "C:\\Users\\user\\source\\repos\\CapsLockChecker\\CapsLockChecker\\if_Circle_Red_34214.png";
            }
        }

        protected override void OnFormClosed(FormClosedEventArgs e)
        {
            Application.Idle -= Application_Idle;
            base.OnFormClosed(e);
        }
    }
}

【问题讨论】:

  • 我会改用计时器来监控。像 50 毫秒或 100 毫秒这样的合理时间不会被用户注意到,但会大大降低 CPU 负载。顺便说一句,感谢您为您的问题付出的努力。它使回答变得更加容易。
  • Application.Idle 被调用太频繁了。您应该在该代码中做尽可能少的事情,并且轮询密钥状态太多了。改用计时器;您不可能需要频繁更新键盘状态。如果您改为每四分之一秒 (250 毫秒) 轮询一次,用户将不会注意到延迟,并且您将使用更少的 CPU。
  • 更好的是,在按下 CapsLock 时捕获事件。
  • Application.Idle 并没有什么问题,其实是一个很好的发现程序bug的方法。该问题是由 PictureBox.ImageLocation 分配引起的。它假定它总是必须重新加载图像,即使它是同一个文件。除了燃烧 100% 核心之外,您还应该看到程序的内存使用量猛增。恭喜,这样的错误很难找到,而且这里也没有人看到它。做对了this way.
  • @HansPassant 谢谢汉斯,我很高兴我发现了一些新东西;)

标签: c#


【解决方案1】:
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        this.KeyDown += CapsLockMonitor;
        this.KeyPreview = true;
    }

    private void CapsLockMonitor(object sender, KeyEventArgs e)
    {
        if (Control.IsKeyLocked(Keys.CapsLock))
        {
            this.label1.Text = "Caps lock enabled!";
        }
        else
        {
            this.label1.Text = "Caps lock disabled!";
        }
    }
}

这似乎不会占用我所有的 CPU,我使用自定义委托订阅了 KeyDown 事件。

【讨论】:

  • 这很有趣,谢谢。它可以工作,但只有在表单处于活动状态时,如果选择了不同的窗口,大写锁定状态不会改变,你认为计时器会有帮助吗?
  • github.com/gmamaladze/globalmousekeyhook 我会检查一下,它和我的代码做同样的事情,除了你可以监听应用程序之外的事件。
【解决方案2】:

老实说,保持CapsLock 状态持续受到监控,即使应用程序处于空闲状态,这对我来说似乎有点过头了。我的意思是,我不怀疑这是一个不错的功能,但我不知道是否值得为实现它付出努力。

如果您的应用程序必须在他的CapsLock 开启时在用户输入内容时警告用户,最好(也是更简单)的方法是在用户关注某个Control 允许文本编辑。即使代码基于WPF 框架,你也有一个很好的例子来说明我所说的here

为了执行您要查找的内容,您需要建立一个基于Global Keyboard Hook 的非常复杂的系统。在this link 之后,您可以找到一篇非常精彩且详细的文章(“在 C# 中处理全局鼠标和键盘挂钩”),该文章描述了如何完成此任务。该链接还包含一个用C# 编写的演示代码,您可以部署和尝试。

摘录:

这个类允许你点击键盘和鼠标和/或检测它们 活动,即使应用程序在后台运行或不运行 有任何用户界面。此类引发常见的 .NET 事件 使用 KeyEventArgs 和 MouseEventArgs,因此您可以轻松检索任何 您需要的信息。

【讨论】:

    猜你喜欢
    • 2013-05-02
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 2014-07-16
    • 2014-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多