【问题标题】:Is there anyway I can break from an infinite loop with a "hotkey" so to say?无论如何我可以用“热键”打破无限循环吗?
【发布时间】:2014-01-13 02:24:42
【问题描述】:

我正在编写这个程序,我想通过一个while循环永远运行,每当用户按下键盘上的某个键时,它就会退出程序。我到处都看过,但我只看到了 KeyEvents,但 WindowsForm 在程序运行时没有激活。谁有我的解决方案?

编辑:程序接管光标,因此在 UI 上激活事件基本上是不可能的

编辑二:

    public void MainMethod() 
    {
        while (true) 
        {
            if (checkBox1.Checked == true) state = State.PERFORM_ACTION_ONE;
            if (checkBox2.Checked == true) state = State.PERFORM_ACTION_TWO;
            // More stuff checking which state to assign

            switch (state) 
            {

            case State.PERFORM_ACTION_ONE:
                 DoSomething();
                 break;
            // More cases
            // I want it to be able to break anywhere in the while loop
            }
        }
    }

【问题讨论】:

  • 你说的是处理Ctrl+C in console application 吗?
  • 这里没有线程问题或其他任何问题。他问“如何在未聚焦时使用键盘关闭我的应用程序?”而已。 while loop 根本不相关。对于他的问题,答案是热键。
  • @Rudy - 我明白了......我确实以完全不同的方式阅读了这个问题(可能是因为无限 while 在 WinForm 应用程序中对我来说并没有真正意义,并且可能是由于缺少 WinForms 标签) ...现在感觉更像XY problem - 也许如果 OP 解释了实际目标是什么,我们可以找到比全局钩子更痛苦的解决方案。
  • 你在写什么类型的应用程序?服务?安慰? WinForm?
  • 你不能在 UI 线程上运行那个紧密的循环。您必须在后台线程上运行循环。

标签: c# winforms


【解决方案1】:

您需要像这里Set global hotkeys using C# 一样设置一个热键,然后使用该热键退出应用程序。

【讨论】:

  • 这不起作用,它一直说我不能使用 ModifierKeys 枚举作为实例引用,而是将其限定为类型名称(IDK 怎么做)
  • @Ipwnusck,您需要在问题中添加代码。如果我们看不到您写的内容,我们将无法帮助您。
  • @BlackFrog 我在下面的问题中完全按照它的方式编写了代码,它没有工作。
【解决方案2】:

您需要在与 UI 线程不同的线程中运行无限循环。并且有一个无限循环来检查可以从 UI 线程设置的变量:

while (keepRunning){
  // do stuff
}

然后在按下按钮时设置事件以将keepRunning 更改为false。

这里是快速示例:

public partial class Form1 : Form
{
    public static bool KeepRunning;

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        KeepRunning = true;
        Task.Factory.StartNew(() =>
                              {
                                  while (KeepRunning)
                                  {
                                      Trace.WriteLine("Keep running");
                                  }
                              });
    }

    private void button2_Click(object sender, EventArgs e)
    {
        KeepRunning = false;
        Trace.WriteLine("Finished Execution");
    }
}

【讨论】:

  • 请注意,您需要volatile 或其他形式的同步。
  • 是的,当然。但是,如果只有一个线程写入,其他线程读取,OP 可以在不深入多线程的情况下逃脱。
  • 仍然需要同步,否则工作线程可能永远看不到更新的值。
  • 除非您将KeepRunning 声明为静态,否则不会。查看代码更新示例。
  • “当用户按下键盘上的某个键时,它会退出程序”和“WindowsForm 在程序运行时不活动”怎么样?
【解决方案3】:

如果你在另一个线程中启动循环,你可以在你点击“热键”或任何你想停止它的时候取消它正在运行的线程。查看BackgroundWorker

【讨论】:

  • 当我找到热键的解决方案后,我正在考虑使用单独的线程,一个线程在运行,而另一个线程则在循环主动搜索是否按下了热键。
【解决方案4】:

将循环放入单独的Task

WinForms 将继续在 UI 线程上并发运行,因此它可以继续接收用户输入。当用户要求您停止时,您可以使用任务取消机制1退出循环和任务本身。


1参见“取消任务”部分here

【讨论】:

  • 不访问 WinForm 用户如何请求程序停止?
  • @Ipwnusck “不访问 Winforms”是什么意思?整个想法是允许 WinForms 继续处理用户输入,即使您的“无限循环”正在运行。
  • @Ipwnusck 你说你有一个永远运行的while循环。这样的循环会阻塞 UI 线程并阻止它处理任何用户输入。我的回答是解决这个问题。如果您有不同的问题,请澄清。
  • 好吧,我的问题是,如果用户在键盘上键入某个键而 WinForm 没有聚焦,那么 WinForm 应用程序是否可以退出
  • @Ipwnusck 好的,那么您应该这么说;)您必须为此注册一个全局热键。您必须 P/Invoke Win32 API(类似于this) - 我认为没有方便的 .NET 包装器。
猜你喜欢
  • 1970-01-01
  • 2013-03-08
  • 1970-01-01
  • 2012-04-02
  • 1970-01-01
  • 2018-09-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-04
相关资源
最近更新 更多