1

I have been dealing with really strange thing. In debug mode or if Thread.Sleep is set above 1900ms everything is fine, but if I'm not in debug mode a function OnKeyPressed is called twice while the function is still running.I thought, that it's because EventHandler calls OnKeyPressed twice, but when I pressed the key programmatically nothing has changed. What's more I have observed that the Thread.Sleep is called just one time. How do I know the code is executed two times? I have 2 the same objects in my savedWords collection. Some details of the code I've written:

I have a Listbox<string> savedWords where I keep text from clipboard. I am using an InputSimulator Framework to simulate keyboard events(only to send key combination). I have a simple InputClass where I obtain a method CopyText in order to simulate key combination of ctrl+c to save the text in clipboard. I'm not able to get into the clipboard if I'm not using STA Attribute, so it has to be there. In order to hook the keyboard(to listening if the key I want to is pressed) I'm using the second solution(with the HandledEventArgs) from here Global keyboard capture in C# application . Here is my code:

private void OnKeyPressed(object sender, GlobalKeyboardHookEventArgs e)
{
       if (e.KeyboardData.VirtualCode==(int)Keys.F1)
    {
        string storedText="";
        e.Handled = true;
        System.Windows.Clipboard.Clear();
        Thread.Sleep(50);
        Thread t = new Thread(
            () => { storedText = pasteMethod.CopyText(); }
            );
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
        t.Join();

        System.Threading.Thread.Sleep(1900); // If I set the time below 1900 it executes twice

        if (!String.IsNullOrWhiteSpace(storedText))
        {
            savedWords.Add(storedText); //Here I add the text from clipboard to my collection and it's the part of code which is called twice
        }
    }
Developer Guy
  • 2,318
  • 6
  • 19
  • 37
wsdsad
  • 15
  • 5
  • what is the qs ? How to know how many times a code was executed ? popping a `MessageBox` or `Console` won't be much of a work,or would it ? – Software Dev Apr 05 '18 at 20:46
  • Why are you kicking off a thread just to `.Join` it right away? Seems counter-productive... – Ron Beyer Apr 05 '18 at 20:47
  • @RonBeyer Looks like the code needs to run in an STA thread. Apparently the current thread isn't (which seems weird, but that'd be the only reason the code would make sense). – Servy Apr 05 '18 at 20:48
  • @Servy Right, if it is Winforms or WPF, it is already STA... – Ron Beyer Apr 05 '18 at 20:49
  • It's WPF, but without it IT won't work. I know how many times the code is executed - 2. And yes I can use Debug.WriteLine to check it. – wsdsad Apr 05 '18 at 20:57
  • @wsdsad any updates on your challenge? – S.C. Apr 07 '18 at 00:52

1 Answers1

0

Taking a wild guess here, but the neither the keyboard hook you referenced nor your use of it filter the keyboard event by the event type. There are four event types based on this doc: WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, and WM_SYSKEYUP. If you are processing both the key down and key up event or processing the key down event repeatedly depending on the repeat count, you will have your event handler called multiple times for the same conceptual key press. The keyboard hook you referenced passes the event type to its registered handlers, so you can filter on that and only handle the key up events to ensure that no matter how long the key is pressed you handle its press only one time.

Also, if you are only handling a specific key press event, you might want to consider registering a global hotkey instead of processing a hook callback for every unrelated key press.

S.C.
  • 1,152
  • 8
  • 13