【问题标题】:How to run an infinite loop without hanging the program? (c#)如何在不挂起程序的情况下运行无限循环? (C#)
【发布时间】:2011-11-04 15:04:49
【问题描述】:

我在 c# 程序中使用线程,但是线程运行的进程调用另一个函数,该函数具有锁定程序的无限循环,也就是说,如果我单击另一个选项Windows 窗体(例如:关闭等)将不再响应。

这个循环是必要的,目前还不能改变。

有没有一种方法可以让我像“背景”一样运行这个循环并且仍然使用程序中的其他选项,这是:循环不会阻塞进程(我不喜欢在线程内部使用线程!)。

Main Program
     |
     -------Thread(Function)
                       |
                       --------In the function ANOTHER
                               function is called with 
                               an infinite loop inside 
                               (this loop is NOT part of the 
                                Thread function directly)     

编辑:添加一些示例代码:

//Here I call the threads
private void userTest_Click(object sender, EventArgs e)
    {
        for (int i = 0; i < numberOfDevices; i++)
        {
            try
            {
            Thread t = new Thread(unused => device(i, sender, e));
            t.IsBackground = true;
            t.Start();
            }
            catch (ThreadStateException f)
            {
                MessageBox.Show("ERROR:" + f);  // Display text of exception
            }
         }
      }

线程函数:

    //This infinite loop is useless, so it could be deleted. This is not
    // the loop I´m talking about
    public void device(object i, object s, object f)
    {
        while (true)
        {
            if (!killEm)
            {
                int j = (int)i;
                EventArgs g = (EventArgs)f;
                BSSDK.BS_SetDeviceID(m_ConnectedDeviceHandle[j],
                 m_ConnectedDeviceID[j], m_ConnectedDeviceType[j]);

                UserManagement userTest = new UserManagement();


                userTest.SetDevice(m_ConnectedDeviceHandle[j],
                    m_ConnectedDeviceID[j], m_ConnectedDeviceType[j]);
                userTest.ShowDialog();

            }
            else
            {
                userTest.Dispose();
                MessageBox.Show("Why don´t u kill it!!?");
                break;
            }
        }
    }

userTest.ShowDialog() 函数中是我所说的无限循环

EDIT 这是 userTest.ShowDialog()

中调用的函数的一部分
private void user_Click(object sender, EventArgs e) {

//THIS IS THE LOOP I´M TALKING!
while (true) {
    Keep listening for an user put his finger in the device
    ...
    Do things with that finger template
    ...   
}

}

谢谢。

【问题讨论】:

  • 请向我们展示您的代码;如果您正确使用线程,则不会发生这种情况。
  • 你需要异步运行线程。
  • 那么让我直截了当 - 你是在一个新线程上打开一个新窗口并在那个新窗口内运行一个无限循环?
  • @Toomai :是的,这正是我正在做的事情
  • @Kani 错了,错了,错了。进程包含线程。线程执行进程。 (虽然在线程中运行的代码可以生成另一个进程...这肯定不是这里发生的...)

标签: c# process infinite-loop


【解决方案1】:

好的;好消息是:您根本不需要线程。您在这里基本上拥有的是“表单”形式的常规 Windows 窗体组件。这些表格必须保持“活跃”,以响应事件。不过,您不需要创建线程来执行此操作。

关键是 System.Windows.Forms.Application 静态类,它有一个为您在这里需要的功能量身定制的功能。

System.Windows.Forms.Application.Run();

此方法可让您的 Form 对象继续运行,响应事件,而无需让调用它的函数继续。它“阻塞”,让消息泵响应,直到调用 Application.Exit() 或其他类似方法。

在您的情况下,您要做的是创建所有表单,然后依次调用每个表单上的Show()不是ShowDialog()),然后最后调用Application.Run()。这会让你得到你想要的。

为了结束您的程序,您需要在某处调用Application.Exit() 以响应某事。您有两个可以快速为您工作的选项:

  • 创建一个单独的“控制表单”,它只是一个普通表单,在关闭时调用Application.Exit(),可能是在循环浏览所有 userManagement 表单并首先关闭它们之后。例如,您可以通过控件表单的 Form.OnClosing 事件上的事件来执行此操作。
  • 向每个 userManagement 表单的 Form.OnClosing 事件添加一个事件,以检查最后一个表单何时关闭(或者是否其中任何一个已关闭?),并且像上面一样,在那里调用 Application.Exit()。李>

一旦你调用Application.Exit(),任何打开的表单都应该被拆除(我建议首先手动进行......)然后你在主线程中对Application.Run()的调用将完成,允许你的程序继续。 .. 我们假设,结束。


编辑:老答案,为了后代......

你在错误的地方创建了新线程。

不要为第二个窗口创建新线程。相反,为长时间运行的任务创建一个新线程,并确保将其设置为后台线程,这样即使关闭窗口它也不会保持活动状态。

理想情况下,这个循环应该有办法优雅地取消,但你似乎建议你不能碰那个代码......

【讨论】:

  • 嗯,我为第二个窗口创建线程的原因是因为这个窗口代表一个“设备”,我必须拥有与设备一样多的线程。它们必须同时运行。为长时间运行的任务创建线程是什么意思?在这种情况下,会是什么? (对不起,我的线程经验非常少)
  • @Kani 好的,我刚刚查看了您发布的代码,我有一两个问题... UserTest 是一个来自您正在使用的 SDK 的 Form 对象,这就是您需要继续运行,哪些是你无法改变的?
  • AndrewBarber : 无法更改 user_Click 中的 while 循环,该循环是 userTest.ShowDialog() 的乘积函数。该函数具有我正在谈论的循环。线程在这里什么都不做——问题将是相同的没有线程——我只是说那个函数是由一个线程调用的。
  • @Kani 好的,我想我已经弄清楚了。我将编辑我的答案,完成后我会再次回复以通知您。
  • @Kani 好的;我已经编辑了我认为正在发生的事情的答案。让我知道你的想法。
【解决方案2】:

你应该避免繁忙的循环,为什么你不能循环一些睡眠或暂停的系统调用?

【讨论】:

    【解决方案3】:

    除了这是否是个好主意之外,您是否尝试过 BackgroundWorker?

    http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=VS.80).aspx

    【讨论】:

    • 好吧,即使我使用 BackgroundWorker,无限循环也会被锁定——据我了解文档——因为我无法“分段”那部分代码。好吧,我可以把它变成一个函数并尝试。让我试试看。
    【解决方案4】:

    【讨论】:

    • 哇,如果我在线程中使用线程,程序的逻辑会更加模糊。如果可能的话,我想避免这种情况。不过,如果根据您的经验,这是解决问题的标准方法,我可以尝试一下!
    • @Kani 真的没有“线程内的线程”这样的东西。你从哪里得到这个想法?
    • 对不起,我想说的是,在程序的逻辑中,我会调用一个线程,在这个线程的过程中我会调用另一个线程。当然,线程就是线程。但是如果我模糊了程序的逻辑,在一个已经很复杂的生物识别程序中维护将非常困难:/
    【解决方案5】:

    这与线程无关——即使你从主线程调用这个“无限循环函数”,它仍然会挂起你的程序。

    所以,无论是谁编写了这个函数,他/她都必须实现一些机制来阻止它,否则它会毫无用处。没有强行终止线程 (Thread.Abort),我建议调查此机制并将其用于您的线程。

    顺便说一句,这个函数的目的是什么?某种消息处理?

    --- 编辑---

    好的,所以你的“无限循环”实际上是Form.ShowDialog。它在内部包含一个消息泵,并且以编程方式停止该泵的方法是设置Form.DialogResult。请注意,您需要将所有 UI 调用编组到正确的线程,如 this post 所示。

    另外,请尝试通过 Application.Run(Form) 运行您的 from,而不是 Form.ShowDialog

    【讨论】:

    • 我经常运行生物识别设备的指纹功能,因此可以在用户放手指时识别用户。必须一直在听(循环)。我确实实现了无限循环,但我没有找到另一种让设备一直监听的方法:/
    • @Kani 您有一个循环这一事实与该循环的 infinity 无关。有几种方法可以停止这种循环,从简单的方法(例如设置由循环本身检查的bool 标志)到更复杂的方法(例如 TPL 任务取消)。在您的情况下,您可以有效地将“关闭对话框”消息传递给对话框的消息泵(请参阅编辑)。
    • 问题是循环应该永远停止。即使在生产时间,它也必须 24/7 不间断地运行。我不想停止循环,我需要的是使用循环但锁定程序。由于“无限循环”-buggy- 的内在本质,也许是不可能的。 (感谢DialogResult的提示,我将在另一部分代码中使用。更优雅)
    • @Kani “越野车”?如果你的意思是你的代码......你似乎试图以正确的方式做到这一点。
    • @Kani 我不知道你从哪里得到关于线程如何工作的想法,我不知道有多少麻烦是你使用术语的不精确性质(线程不调用函数......他们执行它们)......但我看不到任何地方。
    猜你喜欢
    • 1970-01-01
    • 2022-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 2022-07-01
    相关资源
    最近更新 更多