问题
I am using the code from this article :
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);
with a little modification but sometimes when i press a couple of keystrokes too fast then the computer "slows" down a bit and gets a little "laggy".
So when it hits asyncronosly the event HookCallback it sometimes get a little laggy, but i guess its the code in this method "HookCallback" that makes it laggy or is it the hooking it self? I had an idea about creating a new thread everytime i enter "HookCallback" , that maybe will help but do i want to start a new thread everytime i press a key? I am getting an asyncronosly call already so i dont know if i should start another thread besides that.
So my question is simple, where and why does it slow down the computer, is it the hooking it self or is it the custom code ? Or should i put the custom code in a different thread?
And i have another question, sometimes after a few keypresses "HookCallback" doesnt get called, as if i have "unhooked" the event, and it wont capture any keystrokes at all. How can i make sure that it never unhooks the event unless i do it in manually?
Thank you.
回答1:
I've spent a fair amount of time doing keyboard hooks, so the following is just my own experience. Hooks need to be efficient. I wrote a small POS app a few years ago that had to capture keystrokes. It was written in C#, and slowed the input to the point of becoming noticeable. After a lot of headaches I finally realized that the big lag was coming from the translation from native code to managed code. I re-wrote small pieces of the hook code in C++ (native) and saw improvements that I would deem "good enough".
Just remember that speed is fully determined by how long your code takes to process it. Try your very best to make it efficient.
回答2:
There is another factor about "unhook" problem. If your low level global hook codes can not finish in certain amount of time, the OS will remove your hook automatically without notifying you. So make your codes run as fast as possible
Cheers
回答3:
If you want to capture keystrokes within your application only, things can be faster then; use WH_KEYBOARD
instead of WH_KEYBOARD_LL
, this will make much more noticeable performance increase.
private const int WH_KEYBOARD = 2;
回答4:
I had the same symptoms, but it turned out my issue was due to Thread.Sleep(); I had recently changed my application from a Console to Windows Application. My code had been:
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();
}
This made windows slow down incredibly, even though all my hook does is increment a global variable whenever the keyboard is used. When I changed it to the following, my lag issue was resolved:
static void Main( string[] args )
{
hook_keys();
var application = new Application();
application.Run();
unhook_keys();
}
来源:https://stackoverflow.com/questions/6891570/global-keyboard-hook-slowing-down-computer