-1

I'm currently building an application where a user has a list of items that need to be triggered. The operator triggers this using a shortcut ("ADD"-button). Now most items only consist out of one action which is being executed, however, there are some items that include multiple steps. These steps need to be controlled by the operator.

So eventhough it is one item which is being triggered, the steps inside of the item need to be controlled by the shortcut.

private void function triggerItem()
{
   // Perform Step 1
   // PAUSE (AWAIT KEYPRESS)
   // Perform Step 2
   // PAUSE (AWAIT KEYPRESS)
   // Perform Step 3
}

So for now in order to test it, I have just used a messagebox to "pause" in between the different steps, but I would like to make it a bit more clear. So I have created a panel with a keydown event that can capture the "ADD"-button being pressed to make the function continue.

But I think I would need a sort of Task that I can await the result for before continuing with the rest of the actions. Except I can't see how I can await a keydown event from a panel to return a value to the await function.

How could I achieve this?

private void showWarning()
{
    // SHOW THE WARNING
    panWarning.Show();

    // ENSURE THE FOCUS IS SET TO THE PANEL TO CAPTURE THE KEY DOWN EVENT
    panWarning.Focus();

    // AWAIT THE KEYPRESS TO CONTINUE THE FUNCTION
}

    private void panWarning_KeyDown(object sender, KeyEventArgs e)
    {
        // CHECK WHICH BUTTON WAS PRESSED
        switch (e.KeyCode)
        {
            case Keys.Add:
                // CONTINUE
                break;

            case Keys.Escape:
                // ABORT
                break;
        }    
    }

Any suggestions? Thank you.

Cainnech
  • 439
  • 1
  • 5
  • 17
  • 1
    Why not just run the rest of the method (break it apart so it can be run separately) when your state is set and the keydown event is fired? Otherwise use an async AutoResetEvent or a TaskCompletionSource. Note both of those last solutions can be nuanced, so they will need to be researched – TheGeneral Oct 19 '21 at 21:35
  • 1
    Related answer: [Is it possible to await an event?](https://stackoverflow.com/a/12858633/2791540) – John Wu Oct 19 '21 at 21:36
  • While I agree with you @TheGeneral, it would be the proper thing to run everything separately, but that would mean I would have to keep track of which Item I'm currently executing which in my case cause a lot of overhead for an application which will only be used once during an event. – Cainnech Oct 19 '21 at 21:54

1 Answers1

0

You can use a TaskCompletionSource to await anything. To solve your problem, create one and set its result in an event handler.

A method like this one will do it:

public async Task WaitForKey(Control control)
{
    var tcs = new TaskCompletionSource<bool>();

    void LocalHandler(object s, EventArgs a)
    {
        tcs.SetResult(true);
    }
    control.KeyDown += LocalHandler;
    await tcs.Task;
    control.KeyDown -= LocalHandler;
}

And you'd call it like this:

private async Task TriggerItem()
{
    // Perform Step 1
    await WaitForKey(this);
    // Perform Step 2
    await WaitForKey(this);
    // Perform Step 3
}

Note that if you are awaiting a keypress on the form itself, you may need to set KeyPreview to true.

John Wu
  • 50,556
  • 8
  • 44
  • 80