I'm writing an application which requires key presses to be monitored in the background. This is the current code I'm using, with which I've tried many different methods of detecting key presses and debugged using breakpoints to no success. I should mention (if it's not obvious) that I'm new to asynchronous programming and I still only understand it on a very low level.
private async void Form2_Load(object sender, EventArgs e)
{
await KeyboardPressSearch();
}
private static async Task<bool> KeyboardPressSearch()
{
await Task.Delay(5000);
while (true)
{
if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
{
var p = new Process();
p.StartInfo.FileName = @"C:\Program Files\REAPER (x64)\reaper.exe";
p.Start();
return true;
}
}
}
What would you recommend I do or change? Thank you.
CodePudding user response:
As Theodor Zoulias mentioned in the comments, you can achieve this behavior by setting Form.KeyPreview
to true
and registering the KeyPress
event.
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.ShiftKey)
{
var p = new Process();
p.StartInfo.FileName = @"C:\Program Files\REAPER (x64)\reaper.exe";
p.Start();
//e.Handled = true if you don't want the other controls to see this keypress
e.Handled = true;
}
}
This code will now by definition be asynchronous, since it doesn't wait until the keypress, but reacts to it. If you really need to await
a Task
object somewhere, one that will complete once this event's condition is satisfied, use TaskCompletionSource
:
public Task KeyboardPressSearch()
{
// Invoking is used so that localFunc() is always executed on the UI thread.
// locks or atomic operations can be used instead
return
InvokeRequired
? Invoke(localFunc)
: localFunc();
Task localFunc()
{
taskCompletionSource ??= new();
return taskCompletionSource.Task;
}
}
private TaskCompletionSource? taskCompletionSource;
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.ShiftKey)
{
var p = new Process();
p.StartInfo.FileName = @"C:\Program Files\REAPER (x64)\reaper.exe";
p.Start();
//e.Handled = true if you don't want the other controls to see this keypress
e.Handled = true;
if(taskCompletionSource is not null)
{
taskCompletionSource.SetResult();
taskCompletionSource = null;
}
}
}