Maison > développement back-end > C++ > Pourquoi mon crochet de clavier global en C# cesse-t-il de fonctionner après des frappes prolongées ?

Pourquoi mon crochet de clavier global en C# cesse-t-il de fonctionner après des frappes prolongées ?

Barbara Streisand
Libérer: 2025-01-03 08:34:42
original
321 Les gens l'ont consulté

Why Does My Global Keyboard Hook in C# Stop Working After Sustained Keystrokes?

Utilisation du hook de clavier global (WH_KEYBOARD_LL) dans WPF/C#

Le code fourni vise à établir un hook de clavier global en utilisant le hook WH_KEYBOARD_LL pour capturer et traiter les événements du clavier. Alors que l'implémentation atteint essentiellement la fonctionnalité prévue, un problème crucial se pose : après une période de frappes soutenues, la gestion des événements cesse brusquement.

Ce comportement suggère un problème potentiel de threading. Pour résoudre ce problème, nous devons nous assurer que le délégué de rappel reste en vie tant que le hook est en place.

Analyse du problème

Le délégué de rappel, HookCallback, est défini en ligne dans la méthode SetHook. Par conséquent, le délégué est éligible au garbage collection une fois la méthode terminée. Lorsque cela se produit, le hook cessera de recevoir des rappels, ce qui entraînera l'arrêt observé de la gestion des événements.

Solution

Pour rectifier cela, nous devons conserver une référence à le délégué et assurez-vous que sa durée de vie coïncide avec l’existence du hook. Voici le code révisé qui résout le problème :

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Windows.Input;

namespace MYCOMPANYHERE.WPF.KeyboardHelper
{
    public class KeyboardListener : IDisposable
    {
        private static IntPtr hookId = IntPtr.Zero;
        private InterceptKeys.LowLevelKeyboardProc callback;

        public KeyboardListener()
        {
            callback = HookCallback;
            hookId = InterceptKeys.SetHook(callback);
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            try
            {
                return HookCallbackInner(nCode, wParam, lParam);
            }
            catch
            {
                Console.WriteLine("There was some error somewhere...");
            }
            return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam);
        }

        private IntPtr HookCallbackInner(int nCode, IntPtr wParam, IntPtr lParam)
        {
            // ... (original code here)

            return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam);
        }

        // ... (rest of the class)
    }
}
Copier après la connexion

Dans ce code mis à jour, le délégué LowLevelKeyboardProc (rappel) est désormais un champ de la classe KeyboardListener. En conservant cette référence, nous garantissons que le délégué reste en vie et disponible pour les appels de rappel tout au long de la durée de vie du hook.

En résolvant le problème de thread de cette manière, le hook de clavier global continuera à capturer et à traiter les événements du clavier de manière fiable. , même dans des scénarios de frappes incessantes.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal