ホームページ >バックエンド開発 >C++ >キーストロークを続けると、C# のグローバル キーボード フックが機能しなくなるのはなぜですか?

キーストロークを続けると、C# のグローバル キーボード フックが機能しなくなるのはなぜですか?

Barbara Streisand
Barbara Streisandオリジナル
2025-01-03 08:34:42307ブラウズ

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

WPF / C# でのグローバル キーボード フック (WH_KEYBOARD_LL) の使用

提供されたコードは、WH_KEYBOARD_LL フックを使用してグローバル キーボード フックを確立することを目的としています。キーボードイベントをキャプチャして処理します。この実装は基本的に意図した機能を実現しますが、重大な問題が発生します。キーストロークが一定期間続くと、イベント処理が突然停止します。

この動作は、スレッドの問題の可能性を示唆しています。これを解決するには、フックが存在する限りコールバック デリゲートが生き続けることを確認する必要があります。

問題分析

コールバック デリゲート HookCallback は次のとおりです。 SetHook メソッド内でインラインで定義されます。したがって、メソッドが終了すると、デリゲートはガベージ コレクションの対象になります。これが発生すると、フックはコールバックの受信を停止し、イベント処理の終了が観察されます。

解決策

これを修正するには、への参照を保持する必要があります。デリゲートを管理し、その存続期間がフックの存在と一致することを確認します。この問題に対処する修正されたコードは次のとおりです。

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)
    }
}

この更新されたコードでは、LowLevelKeyboardProc デリゲート (コールバック) が KeyboardListener クラスのフィールドになりました。この参照を維持することで、フックの存続期間中、デリゲートが生き続け、コールバック呼び出しに利用できることが保証されます。

この方法でスレッドの問題に対処することで、グローバル キーボード フックは引き続きキーボード イベントを確実にキャプチャして処理します。容赦ないキーストロークのシナリオでも。

以上がキーストロークを続けると、C# のグローバル キーボード フックが機能しなくなるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。