глобальный хук клавиатуры замедляет работу компьютера - PullRequest
1 голос
/ 31 июля 2011

Я использую код из этой статьи :

private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;

public static void Main()
{
    _hookID = SetHook(_proc);
    //Application.Run();
    //UnhookWindowsHookEx(_hookID);
}

private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
    using (Process curProcess = Process.GetCurrentProcess())
    using (ProcessModule curModule = curProcess.MainModule)
    {
        return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
            GetModuleHandle(curModule.ModuleName), 0);
    }
}

private delegate IntPtr LowLevelKeyboardProc(
    int nCode, IntPtr wParam, IntPtr lParam);

private static IntPtr HookCallback(
    int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
    {
        int vkCode = Marshal.ReadInt32(lParam);
        ***custom code***
    }
    return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
    LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
    IntPtr wParam, IntPtr lParam);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);

с небольшими изменениями, но иногда, когда я нажимаю пару нажатий клавиш слишком быстро, компьютер "тормозит"немного и становится немного "запаздывающим".

Так что, когда оно асинхронно попадает в событие HookCallback, оно иногда становится немного запаздывающим, но я предполагаю, что код в этом методе "HookCallback" делает его запаздывающим илизацепить себя?У меня была идея о создании новой темы каждый раз, когда я вхожу в «HookCallback», это может помочь, но хочу ли я создавать новую тему каждый раз, когда я нажимаю клавишу?Я уже получаю асинхронный вызов, так что я не знаю, должен ли я запускать другой поток, кроме этого.

Так что мой вопрос прост: где и почему он замедляет работу компьютера, перехватывает ли он сам себя илиэто пользовательский код?Или я должен поместить пользовательский код в другой поток?

И у меня есть другой вопрос, иногда после нескольких нажатий клавиш «HookCallback» не вызывается, как будто я «отцепил» событие, и он не будет захватыватьлюбые нажатия клавиш вообще.Как я могу убедиться, что оно никогда не отцепит событие, если я не сделаю это вручную?

Спасибо.

Ответы [ 4 ]

2 голосов
/ 31 июля 2011

Я потратил довольно много времени на работу с клавишами, поэтому следующее - только мой собственный опыт. Крючки нужны , чтобы быть эффективными. Несколько лет назад я написал небольшое POS-приложение, которое должно было фиксировать нажатия клавиш. Он был написан на C # и замедлял ввод до такой степени, что становился заметным. После многих головных болей я, наконец, понял, что большая разница в переводе с нативного кода на управляемый код. Я переписал небольшие кусочки кода хука на C ++ (нативный) и увидел улучшения, которые я бы посчитал «достаточно хорошими».

Просто помните, что скорость полностью определяется тем, сколько вашего кода требуется для его обработки. Старайтесь изо всех сил, чтобы сделать его эффективным.

0 голосов
/ 27 ноября 2016

У меня были те же симптомы, но оказалось, что моя проблема была связана с Thread.Sleep (); Недавно я изменил свое приложение с консоли на приложение Windows. Мой код был:

static void Main( string[] args )
{
    hook_keys();
    AppDomain.CurrentDomain.ProcessExit += CurrentDomainOnProcessExit;
    while (true) { System.Threading.Thread.Sleep( new TimeSpan(0,10,0) ); }
}
private static void CurrentDomainOnProcessExit(object sender, EventArgs eventArgs )
{
    unhook_keys();
}

Это заставило Windows замедляться невероятно , хотя все, что я делаю, это увеличивает глобальную переменную всякий раз, когда используется клавиатура. Когда я изменил это на следующее, моя проблема лага была решена:

static void Main( string[] args )
{
    hook_keys();
    var application = new Application();
    application.Run();
    unhook_keys();
}
0 голосов
/ 25 сентября 2011

Есть еще один фактор, связанный с проблемой "отцепить". Если ваши глобальные коды хуков низкого уровня не могут завершиться через определенное время, ОС автоматически удалит ваш хук, не уведомив вас об этом. Сделайте так, чтобы ваши коды работали как можно быстрее

Приветствия

0 голосов
/ 31 июля 2011

Если вы хотите фиксировать нажатия клавиш только в вашем приложении, тогда все может быть быстрее; используйте WH_KEYBOARD вместо WH_KEYBOARD_LL, это значительно повысит производительность.

private const int WH_KEYBOARD = 2;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...