如何在不挂起程序的情况下运行无限循环? (c#)

发布于 2024-12-13 20:32:35 字数 2522 浏览 2 评论 0原文

我在 ac# 程序中使用线程,但是线程运行的进程调用另一个函数,该函数具有锁定程序的无限循环,也就是说,如果我单击 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()函数中是无限循环,我正在谈论

编辑这是 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
    ...   
}

谢谢。

I´m using threads in a c# program, but the process that the threads runs, calls another function that has an infinite loop that locks the program, this is, if I click another option of the Windows Form (ex: close, etc.) it will no longer response.

This loop in necessary and, by now, can not be changed.

Is there a way that I could run this loop like "background" and still use the other options in the program, this is: that the loop does not block the process (I would not like to use threads inside of threads!).

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)     

EDIT: Adding some example code:

//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
            }
         }
      }

The thread function:

    //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;
            }
        }
    }

In the userTest.ShowDialog() function is the infinite loop I´m talking about

EDIT This is part of the function that is called in 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
    ...   
}

}

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

¢好甜 2024-12-20 20:32:35

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

关键是 System.Windows.Forms.Application 静态类,它具有根据您的需要量身定制的函数。

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

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

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

为了结束你的程序,你需要在某个地方调用 Application.Exit() 来响应某些事情。您有两个可以快速使用的选项:

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

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


EDIT: Old answer, for posterity...

您在错误的位置创建新线程。

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

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

Okay; Here's the good news: You don't need threads at all. What you basically have here is a regular Windows Forms component in the form of 'forms'. Those forms must be kept 'active', to respond to events. You don't need to create threads to do this, though.

The key is the System.Windows.Forms.Application static class, which has a function tailor-made for what you need here.

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

This method lets your Form objects run on, responding to events, without letting the function it is called in continue. It 'blocks', letting the message pump respond, until Application.Exit() or some other similar methods are called.

What you want to do in your case is create all of your forms, and call Show() on each one in turn (not ShowDialog()), and then finally call Application.Run(). That gets you what you want.

In order to end your program, you need to have a call to Application.Exit() happen somewhere, in response to something. You have two options that would work quickly for you:

  • Create a separate 'control form' that is just a plain Form that, when closed, calls Application.Exit(), perhaps after cycling through all your userManagement forms and closing them, first. You could do this with an event on the control form's Form.OnClosing event, for example.
  • Add an event to each of the userManagement forms' Form.OnClosing events that checks for when the last one is closed (or perhaps if any of them is closed?) and, like above, call Application.Exit() there.

Once you call Application.Exit(), any open forms should be torn down (I recommend doing it manually, first...) and then your call in the main thread to Application.Run() will complete, allowing your program to continue... we presume, to end.


EDIT: Old answer, for posterity...

You are creating your new thread in the wrong place.

Don't create a new thread for the second window. Instead, create a new thread for the long-running task, and be sure to set it as a background thread, so it doesn't stay alive even when you close the windows.

Ideally, this loop should have a way to be cancelled gracefully, but you seem to suggest you can't touch that code...

甜心小果奶 2024-12-20 20:32:35

您应该避免繁忙循环,为什么不能在某些睡眠或暂停系统调用上循环?

You should avoid busy loops, why cannot you loop on some sleeping or pausing system call?

喜你已久 2024-12-20 20:32:35

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

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

Besides the fact if this is a good idea or not, did you try BackgroundWorker?

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

勿忘初心 2024-12-20 20:32:35

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

因此,无论是谁编写了这个函数,他/她都必须实现一些机制来阻止它,否则它就毫无用处。没有强制终止线程(Thread.Abort),我建议研究这个机制并在你的线程中使用它。

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

--- 编辑 ---

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

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

This has nothing to do with threads - even if you call this "infinite loop function" from the main thread, it would still hang your program.

So, whoever authored this function, he/she mush have implemented some mechanism for stopping it, otherwise it would have been quite useless. Short of forcefully killing the thread (Thread.Abort), I suggest investigating this mechanism and employing it in your thread.

BTW, what is the purpose of this function? Some kind of message processing?

--- EDIT ---

OK, so your "infinite loop" is actually Form.ShowDialog. It internally contains a message pump and a way to stop that pump programmatically would be to set Form.DialogResult. Please note that you need to marshal all the UI calls to the proper threads, as indicated by this post.

Also, try running your from through Application.Run(Form), instead of Form.ShowDialog.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文