C# 控制台:检查按键(Esc)
在您标记这一点之前,我已经尝试了这里找到的几种解决方案(我发誓它不是重复的),并最终导致VS崩溃的错误 编辑:有人说我的循环不起作用。问题不在这里,它与按键有关 这是我的原始代码:C# 控制台:检查按键(Esc),c#,C#,在您标记这一点之前,我已经尝试了这里找到的几种解决方案(我发誓它不是重复的),并最终导致VS崩溃的错误 编辑:有人说我的循环不起作用。问题不在这里,它与按键有关 这是我的原始代码: while (true) { Console.WriteLine("Voer een getal in : "); string invoer = Console.ReadLine();
while (true)
{
Console.WriteLine("Voer een getal in : ");
string invoer = Console.ReadLine();
Console.Write("Voer de macht in waarmee u wilt vermenigvuldigen :");
string macht = Console.ReadLine();
int getal = Convert.ToInt32(invoer);
int getalmacht = Convert.ToInt32(macht);
int uitkomst = (int)Math.Pow(getal, getalmacht);
Console.WriteLine("De macht van " + getal + " is " + uitkomst + " .");
Console.ReadLine();
}
它工作得很好,但它没有寻找按键
下面是一个检查按键并不会抛出错误的:
namespace Democonsole
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press ESC to stop.");
do
{
while (!Console.KeyAvailable)
{
Console.WriteLine("Voer een getal in : ");
string invoer = Console.ReadLine();
Console.Write("Voer de macht in waarmee u wilt vermenigvuldigen :");
string macht = Console.ReadLine();
int getal = Convert.ToInt32(invoer);
int getalmacht = Convert.ToInt32(macht);
int uitkomst = (int)Math.Pow(getal, getalmacht);
Console.WriteLine("De macht van " + getal + " is " + uitkomst + " .");
Console.ReadLine();
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
}
}
}
但是,它在运行crash时会执行此操作,并给出打印屏幕中显示的错误
还有别的办法吗
编辑:添加了更多因请求而尝试的解决方案示例
static void Main(string[] args)
{
var myWorker = new MyWorker();
myWorker.DoStuff();
Console.WriteLine("Press any key to stop...");
Console.ReadKey();
}
中断
错误消息告诉您关于该错误所需了解的几乎所有信息,即您正在尝试将字符串转换为整数,而该字符串无法转换为整数。可能是因为它是空的 不过,这只是问题的一部分,我将在稍后讨论 首先,您的循环结构是错误的。只要没有等待读取的按键,内部循环就会运行。但是就在循环体的末尾,您明确地清除了控制台缓冲区的内容,因此它永远不会退出内部循环 考虑这个最小的例子:
while (!Console.KeyAvailable)
{
Console.ReadLine();
}
假设在遇到while
语句(将跳过整个过程)时没有等待读取的键,内部语句将累积击键中的字符,直到按enter键,然后将字符作为字符串返回。几微秒后,它会检查您是否在回车后按下了另一个键,这几乎是不可能的。因此,这是一种编写无限循环的奇怪方式
下一个问题是,您请求用户输入,并假设输入是有效的。不是的,这就是你之前得到的异常的原因。始终假定用户将输入您的程序不期望的内容,并找出如何处理出错的问题
例如:
string invoer = Console.ReadLine();
int getal;
if (!int.TryParse(invoer, out getal))
{
Console.WriteLine("Invalid value '{0}'", invoer);
continue;
}
如果该值未转换为数字,则将对此进行投诉,并返回到循环的开头。如果值为空,您可能还希望尝试退出循环:
string invoer = Console.ReadLine();
if (string.IsNullOrEmpty(invoer))
break;
int getal;
if (!int.TryParse(invoer, out getal))
{
Console.WriteLine("Invalid value '{0}'", invoer);
continue;
}
这至少为您提供了一条跳出循环的途径,而您目前还没有这种途径。我有一个完全替代的解决方案,使用以下解决方案。标题是,您希望选中esc。就是这样。高度复制自: ConsoleHoKeyManager.cs>
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
namespace ConsoleHotKey
{
public static class HotKeyManager
{
public static event EventHandler<HotKeyEventArgs> HotKeyPressed;
public static int RegisterHotKey(Keys key, KeyModifiers modifiers)
{
_windowReadyEvent.WaitOne();
int id = System.Threading.Interlocked.Increment(ref _id);
_wnd.Invoke(new RegisterHotKeyDelegate(RegisterHotKeyInternal), _hwnd, id, (uint)modifiers, (uint)key);
return id;
}
public static void UnregisterHotKey(int id)
{
_wnd.Invoke(new UnRegisterHotKeyDelegate(UnRegisterHotKeyInternal), _hwnd, id);
}
delegate void RegisterHotKeyDelegate(IntPtr hwnd, int id, uint modifiers, uint key);
delegate void UnRegisterHotKeyDelegate(IntPtr hwnd, int id);
private static void RegisterHotKeyInternal(IntPtr hwnd, int id, uint modifiers, uint key)
{
RegisterHotKey(hwnd, id, modifiers, key);
}
private static void UnRegisterHotKeyInternal(IntPtr hwnd, int id)
{
UnregisterHotKey(_hwnd, id);
}
private static void OnHotKeyPressed(HotKeyEventArgs e)
{
if (HotKeyManager.HotKeyPressed != null)
{
HotKeyManager.HotKeyPressed(null, e);
}
}
private static volatile MessageWindow _wnd;
private static volatile IntPtr _hwnd;
private static ManualResetEvent _windowReadyEvent = new ManualResetEvent(false);
static HotKeyManager()
{
Thread messageLoop = new Thread(delegate()
{
Application.Run(new MessageWindow());
});
messageLoop.Name = "MessageLoopThread";
messageLoop.IsBackground = true;
messageLoop.Start();
}
private class MessageWindow : Form
{
public MessageWindow()
{
_wnd = this;
_hwnd = this.Handle;
_windowReadyEvent.Set();
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_HOTKEY)
{
HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
HotKeyManager.OnHotKeyPressed(e);
}
base.WndProc(ref m);
}
protected override void SetVisibleCore(bool value)
{
// Ensure the window never becomes visible
base.SetVisibleCore(false);
}
private const int WM_HOTKEY = 0x312;
}
[DllImport("user32", SetLastError = true)]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
[DllImport("user32", SetLastError = true)]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
private static int _id = 0;
}
public class HotKeyEventArgs : EventArgs
{
public readonly Keys Key;
public readonly KeyModifiers Modifiers;
public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
{
this.Key = key;
this.Modifiers = modifiers;
}
public HotKeyEventArgs(IntPtr hotKeyParam)
{
uint param = (uint)hotKeyParam.ToInt64();
Key = (Keys)((param & 0xffff0000) >> 16);
Modifiers = (KeyModifiers)(param & 0x0000ffff);
}
}
[Flags]
public enum KeyModifiers
{
Alt = 1,
Control = 2,
Shift = 4,
Windows = 8,
NoRepeat = 0x4000,
None = 0
}
}
使用系统;
使用System.Windows.Forms;
使用System.Runtime.InteropServices;
使用系统线程;
命名空间控制台快捷键
{
公共静态类热键管理器
{
按下公共静态事件事件处理程序热键;
公共静态int寄存器hotKey(键键、键修饰符修饰符)
{
_windowReadyEvent.WaitOne();
int id=系统线程联锁增量(参考id);
_调用(新的RegisterHotKeyDelegate(RegisterHotKeyInternal),hwnd,id,(uint)修饰符,(uint)键);
返回id;
}
公共静态void unregister热键(int-id)
{
_调用(新的UnRegisterHotKeyDelegate(UnRegisterHotKeyInternal),\u hwnd,id);
}
委托无效寄存器hotKeyDelegate(IntPtr hwnd、int id、uint修饰符、uint键);
委托无效取消注册HotkeyDelegate(IntPtr hwnd,int id);
私有静态无效寄存器hotKeyInternal(IntPtr hwnd、int id、uint修饰符、uint key)
{
注册表快捷键(hwnd、id、修饰符、键);
}
私有静态void UnRegisterHotKeyInternal(IntPtr hwnd,int id)
{
取消注册热键(_hwnd,id);
}
热键按下时私有静态无效(热键事件参数e)
{
if(HotKeyManager.HotKeyPressed!=null)
{
热键管理器。热键按下(null,e);
}
}
私有静态易失性消息窗口;
私有静态易失性IntPtr\u hwnd;
专用静态手动复位事件\u windowReadyEvent=新手动复位事件(假);
静态热键管理器()
{
Thread messageLoop=新线程(委托()
{
运行(newmessagewindow());
});
messageLoop.Name=“MessageLoopThread”;
messageLoop.IsBackground=true;
messageLoop.Start();
}
私有类消息窗口:窗体
{
公共消息窗口()
{
_wnd=这个;
_hwnd=this.Handle;
_windowReadyEvent.Set();
}
受保护的覆盖无效WndProc(参考消息m)
{
if(m.Msg==WM_热键)
{
HotKeyEventArgs e=新的HotKeyEventArgs(m.LParam);
热键管理器。按下热键(e);
}
基准WndProc(参考m);
}
受保护的覆盖无效SetVisibleCore(布尔值)
{
//确保窗口永远不可见
base.SetVisibleCore(false);
}
私有常量int WM_热键=0x312;
}
[DllImport(“user32”,SetLastError=true)]
私有静态外部布尔寄存器hotkey(IntPtr hWnd、int id、uint fsModifiers、uint vk);
[DllImport(“user32”,SetLastError=true)]
私有静态外部bool unregister热键(IntPtr hWnd,intid);
私有静态int_id=0;
}
公共类HotKeyEventArgs:EventArgs
{
公共只读密钥;
公共只读键修饰符修饰符;
public HotKeyEventArgs(键、键修改器和修改器)
{
这个。键=键;
this.Modifiers=修饰符;
}
public HotKeyEventArgs(IntPtr hotKeyParam)
{
uint参数=(uint)hotKeyParam.T
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
namespace ConsoleHotKey
{
public static class HotKeyManager
{
public static event EventHandler<HotKeyEventArgs> HotKeyPressed;
public static int RegisterHotKey(Keys key, KeyModifiers modifiers)
{
_windowReadyEvent.WaitOne();
int id = System.Threading.Interlocked.Increment(ref _id);
_wnd.Invoke(new RegisterHotKeyDelegate(RegisterHotKeyInternal), _hwnd, id, (uint)modifiers, (uint)key);
return id;
}
public static void UnregisterHotKey(int id)
{
_wnd.Invoke(new UnRegisterHotKeyDelegate(UnRegisterHotKeyInternal), _hwnd, id);
}
delegate void RegisterHotKeyDelegate(IntPtr hwnd, int id, uint modifiers, uint key);
delegate void UnRegisterHotKeyDelegate(IntPtr hwnd, int id);
private static void RegisterHotKeyInternal(IntPtr hwnd, int id, uint modifiers, uint key)
{
RegisterHotKey(hwnd, id, modifiers, key);
}
private static void UnRegisterHotKeyInternal(IntPtr hwnd, int id)
{
UnregisterHotKey(_hwnd, id);
}
private static void OnHotKeyPressed(HotKeyEventArgs e)
{
if (HotKeyManager.HotKeyPressed != null)
{
HotKeyManager.HotKeyPressed(null, e);
}
}
private static volatile MessageWindow _wnd;
private static volatile IntPtr _hwnd;
private static ManualResetEvent _windowReadyEvent = new ManualResetEvent(false);
static HotKeyManager()
{
Thread messageLoop = new Thread(delegate()
{
Application.Run(new MessageWindow());
});
messageLoop.Name = "MessageLoopThread";
messageLoop.IsBackground = true;
messageLoop.Start();
}
private class MessageWindow : Form
{
public MessageWindow()
{
_wnd = this;
_hwnd = this.Handle;
_windowReadyEvent.Set();
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_HOTKEY)
{
HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
HotKeyManager.OnHotKeyPressed(e);
}
base.WndProc(ref m);
}
protected override void SetVisibleCore(bool value)
{
// Ensure the window never becomes visible
base.SetVisibleCore(false);
}
private const int WM_HOTKEY = 0x312;
}
[DllImport("user32", SetLastError = true)]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
[DllImport("user32", SetLastError = true)]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
private static int _id = 0;
}
public class HotKeyEventArgs : EventArgs
{
public readonly Keys Key;
public readonly KeyModifiers Modifiers;
public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
{
this.Key = key;
this.Modifiers = modifiers;
}
public HotKeyEventArgs(IntPtr hotKeyParam)
{
uint param = (uint)hotKeyParam.ToInt64();
Key = (Keys)((param & 0xffff0000) >> 16);
Modifiers = (KeyModifiers)(param & 0x0000ffff);
}
}
[Flags]
public enum KeyModifiers
{
Alt = 1,
Control = 2,
Shift = 4,
Windows = 8,
NoRepeat = 0x4000,
None = 0
}
}
using ConsoleHotKey;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Democonsole
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press ESC to stop.");
HotKeyManager.RegisterHotKey(Keys.Escape, KeyModifiers.None);
HotKeyManager.HotKeyPressed += new EventHandler<HotKeyEventArgs>(Console_CancelKeyPress);
while (true)
{
Console.WriteLine("Voer een getal in : ");
string invoer = Console.ReadLine();
Console.Write("Voer de macht in waarmee u wilt vermenigvuldigen :");
string macht = Console.ReadLine();
int getal = Convert.ToInt32(invoer);
int getalmacht = Convert.ToInt32(macht);
int uitkomst = (int)Math.Pow(getal, getalmacht);
Console.WriteLine("De macht van " + getal + " is " + uitkomst + " .");
Console.ReadLine();
}
}
static void Console_CancelKeyPress(object sender, HotKeyEventArgs e)
{
Environment.Exit(0);
}
}
}