В VB6 я использовал вызов Windows API, GetAsyncKeyState, чтобы определить, нажал ли пользователь клавишу ESC, чтобы позволить ему выйти из длительного цикла.
Declare Function GetAsyncKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Есть ли эквивалент в чистом .NET, который требует прямого вызова API?





Вы можете найти объявление P / Invoke для GetAsyncKeyState в http://pinvoke.net/default.aspx/user32/GetAsyncKeyState.html
Вот, например, подпись C#:
[DllImport("user32.dll")]
static extern short GetAsyncKeyState(int vKey);
В зависимости от желаемого использования есть несколько вариантов, включая вызов того же метода, который описан выше). Из консольного приложения:
bool exitLoop = false;
for(int i=0;i<bigNumber && !exitLoop;i++)
{
// Do Stuff.
if (Console.KeyAvailable)
{
// Read the key and display it (false to hide it)
ConsoleKeyInfo key = Console.ReadKey(true);
if (ConsoleKey.Escape == key.Key)
{
exitLoop=false;
}
}
}
Если вы работаете с формой Windows, каждая форма имеет ряд ключевых событий, которые вы можете прослушивать и обрабатывать по мере необходимости (большая часть упрощенной логики):
public partial class Form1 : Form
{
private bool exitLoop;
public Form1()
{
InitializeComponent();
this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
}
public void doSomething()
{
// reset our exit flag:
this.exitLoop = false;
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(delegate(object notUsed)
{
while (!exitLoop)
{
// Do something
}
}));
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (Keys.Escape == e.KeyCode)
{
e.Handled = true;
this.exitLoop = true;
}
}
}
Обратите внимание, что это упрощенный очень - он не решает никаких обычных проблем с потоками или чего-то подобного. Как было указано в комментариях, исходный цикл не решал эту проблему, я добавил небольшой вызов ThreadPool для потоковой обработки фоновой работы. Также обратите внимание, что проблема с прослушиванием ключевых событий заключается в том, что другие элементы управления могут фактически обрабатывать их, поэтому вам необходимо убедиться, что вы зарегистрировались для события на правильных элементах управления. Если приложение формы Windows - это направление, в котором вы движетесь, вы также можете попытаться ввести себя в сам цикл сообщений ...
public override bool PreProcessMessage(ref Message msg)
{
// Handle the message or pass it to the default handler...
base.PreProcessMessage(msg);
}
Я не думаю, что это сработает, потому что событие KeyUp не сработает, пока выполняется цикл doSomething.