如何在 C# 中异步搜索按键
How do I search for a key press asynchronously in C#
我正在编写一个需要在后台监视按键的应用程序。这是我正在使用的当前代码,我尝试了许多不同的方法来检测按键并使用断点进行调试但没有成功。我应该提一下(如果不是很明显的话)我是异步编程的新手,而且我仍然只在非常低的水平上理解它。
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;
}
}
}
你会推荐我做什么或改变什么?谢谢。
正如 Theodor Zoulias 在评论中提到的,您可以通过将 Form.KeyPreview
设置为 true
并注册 KeyPress
事件来实现此行为。
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;
}
}
根据定义,此代码现在将是异步的,因为它不会等到按键,而是对其做出反应。如果你真的需要await
某处的Task
对象,一旦满足此事件的条件就会完成,请使用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;
}
}
}
我正在编写一个需要在后台监视按键的应用程序。这是我正在使用的当前代码,我尝试了许多不同的方法来检测按键并使用断点进行调试但没有成功。我应该提一下(如果不是很明显的话)我是异步编程的新手,而且我仍然只在非常低的水平上理解它。
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;
}
}
}
你会推荐我做什么或改变什么?谢谢。
正如 Theodor Zoulias 在评论中提到的,您可以通过将 Form.KeyPreview
设置为 true
并注册 KeyPress
事件来实现此行为。
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;
}
}
根据定义,此代码现在将是异步的,因为它不会等到按键,而是对其做出反应。如果你真的需要await
某处的Task
对象,一旦满足此事件的条件就会完成,请使用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;
}
}
}