question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Can't Run Hotkeys Asynchronously

See original GitHub issue

I have two hotkeys set, one to perform an action and the other to cancel it. The problem is that when I call the second hotkey while the first hotkey is doing something, it doesn’t trigger until after the first one is done.

HotkeyManager.Current.AddOrReplace("Paste", HkTextBox.Hotkey.Key, HkTextBox.Hotkey.Modifiers, AutoPaste);
HotkeyManager.Current.AddOrReplace("CancelPaste", Key.Escape, ModifierKeys.Alt, CancelPaste);

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
thomaslevesquecommented, Jan 21, 2021

Task.Factory.StartNew means "run that on a new thread. But Dispatcher.BeginInvoke means “run that on the UI thread”. So there’s no point in starting a new thread just to execute something on the UI thread…

I gave you a few suggestions on how to fix the problem in my previous message, have you tried them? I checked what input.Keyboard.Sleep does, it’s just a Thread.Sleep. So I suggest you do it like this:

private CancellationTokenSource _autoPasteCancellation;

private async void AutoPaste(object sender, HotkeyEventArgs e)
{
    try
    {
        _autoPasteCancellation = new CancellationTokenSource();
        var cancellationToken = _autoPasteCancellation.Token;
        if (WindowState != WindowState.Minimized)
        {
            WindowState = WindowState.Minimized;
            await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
        }

        InputSimulator input = new InputSimulator();

        for (int i = 0; i < clipboardHistoryItems.Count; i++)
        {
            Clipboard.SetHistoryItemAsContent(clipboardHistoryItems[i]);
            await Task.Delay((int)Delay.Value, cancellationToken);
            input.Keyboard.ModifiedKeyStroke(VirtualKeyCode.CONTROL, VirtualKeyCode.VK_V);
            switch (DelimiterComboBox.SelectedIndex)
            {
                case 1:
                    await Task.Delay((int)Delay.Value, cancellationToken);
                    input.Keyboard.KeyPress(VirtualKeyCode.TAB);
                    break;
                ...
            }
        }

        e.Handled = true;

    }
    catch (OperationCanceledException)
    {
        // The operation was aborted
    }
    catch(Exception ex)
    {
        // Always catch exceptions in an async void method, otherwise it can crash the process
        MessageBox.Show(ex.Message);
    }
    finally
    {
        if (_autoPasteCancellation != null)
            _autoPasteCancellation.Dispose();
        _autoPasteCancellation = null;
    }
}

private void CancelPaste(object sender, HotkeyEventArgs e)
{
    if (_autoPasteCancellation != null)
    {
        _autoPasteCancellation.Cancel();
    }
    e.Handled = true;
}

Anyway, the problems you’re having have nothing to do with NHotkey, so I’m going to close this issue.

0reactions
wmortumecommented, Jan 21, 2021

I tried running a new thread on both individually and together but it’s still running synchronously. The only difference this time is that the message box pops up on the screen without me having to click on the application.

private void AutoPaste(object sender, HotkeyEventArgs e)
{
    Task.Factory.StartNew(() =>
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
        {
            if (WindowState != WindowState.Minimized)
            {
                WindowState = WindowState.Minimized;
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }

            Paste = true;
            InputSimulator input = new InputSimulator();

            for (int i = 0; i < clipboardHistoryItems.Count && Paste; i++)
            {
                Clipboard.SetHistoryItemAsContent(clipboardHistoryItems[i]);
                input.Keyboard.Sleep((int)Delay.Value).ModifiedKeyStroke(VirtualKeyCode.CONTROL, VirtualKeyCode.VK_V);
                switch (DelimiterComboBox.SelectedIndex)
                {
                    case 1:
                        input.Keyboard.Sleep((int)Delay.Value).KeyPress(VirtualKeyCode.TAB);
                        break;
                    ...
                }
            }
        }));
    });

private void CancelPaste(object sender, HotkeyEventArgs e)
{
    Task.Factory.StartNew(() =>
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
        {
            MessageBox.Show("Test");
            //Paste = false;
        }));                
    });
    e.Handled = true;
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Asynchronosly launch a method - AutoHotkey Community
Threads are not asynchronous in AutoHotkey. Scripts cannot do two things at once. They can only stop what they're doing to run a...
Read more >
How to async handle callback from keyboard hotkeys?
Need to register global hotkeys. For example, f4 and f8 . With keyboard library while first callback didn't return, the next won't call....
Read more >
Anyway to run shortcut inside another without waiting for it ...
Is there anyway to start a shortcut inside another shortcut without waiting for it to complete? Kinda asynchronous styled?
Read more >
View topic - execute asynchronous
Executing a script asynchronously will create a thread to execute it. This won't block the main thread, but it also means you can't...
Read more >
Intro to the Run JavaScript on Webpage action in Shortcuts ...
Because JavaScript is usually used with asynchronous patterns, the call is intentionally not synchronous. This way, you can finish the action asynchronously.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found