Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 过早取消While循环_Vb.net_Loops_While Loop - Fatal编程技术网

Vb.net 过早取消While循环

Vb.net 过早取消While循环,vb.net,loops,while-loop,Vb.net,Loops,While Loop,我正在使用一个While循环,它根据用户输入的值循环一定数量的周期(1-576)。它是由用户点击“开始”按钮激活的,但我希望它能够被取消,最好是使用“退出”键 然而,当循环进行时,我无法让程序识别任何按键 Private Sub OnGlobalKeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles kh.KeyDown lblInput.Text = Strin

我正在使用一个While循环,它根据用户输入的值循环一定数量的周期(1-576)。它是由用户点击“开始”按钮激活的,但我希望它能够被取消,最好是使用“退出”键

然而,当循环进行时,我无法让程序识别任何按键

Private Sub OnGlobalKeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles kh.KeyDown

        lblInput.Text = String.Format("'{0}' Code:{1}", e.KeyCode, CInt(e.KeyCode).ToString())


        If e.KeyCode = CType(27, Keys) Then
                    count = 0
                    loops = 0
        End If
    End Sub
我的回路

Private Sub RUNLOOP()
            While loops >= 1
                  ' my code that runs in the loop
                  loop = loop - 1
            End While
End Sub

当循环运行时,我的按键没有注册,否则注册很好

在循环中放置以下代码:

Application.DoEvents()
While counter您是否想过使用在后台线程中执行While循环代码(=调整表单大小/重新绘制表单,并让用户“达到”您实现取消运行工作的方式),而无需
应用程序。循环中的DoEvents
是否可以“伪造”此行为


如果您已经使用.NETFramework4.0,您可以尝试使用而不是
BackgroundWorker

有两种方法可以做到这一点。您可以为循环使用单独的线程,也可以使用Application.DoEvents()。线程方法通常会给你最好的结果

螺纹:

只需调用StopLoop()命令循环停止运行。您不希望设置loop=0,因为这样您就必须使用联锁类来确保在线程之间正确设置了loop

Private Sub RunLoop()
  Dim loop As Action = AddressOf InternalRunLoop
  loop.BeginInvoke(null, null)
End Sub

Private bStopLoop As Boolean

Private Sub InternalRunLoop()
  While loops >= 1 And Not bStopLoop
    ' my code that runs in the loop
    loop = loop - 1
  End While
End Sub

Private Sub StopLoop()
  bStopLoop = True
End Sub
事件:

调用Application.DoEvents()将导致处理窗口线程上的所有挂起事件。如果循环的每次迭代都需要一些时间,那么应用程序在用户看来仍然像是没有响应的,这就是为什么首选线程方法的原因

Private SubRunLoop()
  While loops >= 1 And Not bStopLoop
    ' my code that runs in the loop
    loop = loop - 1
    Application.DoEvents()
  End While
End Sub

这在.NET中是个坏主意。当您有一个非常容易使用的BackGroundWorker类时,您不需要这样做,这也会导致可重入性问题-1我理解.Net中的传统设计实践使这成为一个坏主意,但在这个问题的上下文中,这是正确的答案。另一种方法是帮助他对应用程序进行全面的重新设计。你想自告奋勇吗?我不知道添加一个BackGroundWorker和重构一个方法构成了“应用程序的完全重新设计”。OP询问如何使UI保持活动状态,这是一个糟糕的(懒惰的)解决方案。@badbod99:循环中的代码在做什么可能无关紧要,因为它仍将在同一线程上运行。即使他正在做一些事情,比如修改在另一个线程上创建的表单上的控件,或者访问非线程安全的数据结构,也有更好的方法可以做到这一点。老实说,任何人在他们的代码周围胡闹都是在偷懒。@Ed“…就是在偷懒。”或者他们不太清楚,所以要小心指责。但在任何情况下,它都是错误的代码,不应该使用。好吧,我尝试使用BackgroundWorker线程,我相信我已经完成了所有设置,但现在,它说,“跨线程操作无效:从创建它的线程以外的线程访问控件‘cmb_x’。”解决这个问题的办法似乎是修改原始循环中的几乎所有代码,但这是正确的做法。您应该了解这些东西是如何工作的。您是否签出了
Control.invokererequired
?举个例子,我在程序中添加了一个Backgroundworker:但是如何从我的原始线程到我刚刚创建的新工作线程中获取信息呢?循环的数量取决于用户在文本框中输入的数字。我可以通过使用.WorkerReportsProgress从后台工作线程获取信息,但如何让线程从一开始就获取信息?讨厌使用Exit,而逻辑块应该通过逻辑条件正确完成,即计数器>10时。如果出口隐藏在代码中,那么调试会变得很棘手,在本例中很容易看到,因为它只有几行简单的代码,但实际上通常不是这样。Stefan Rusek是更优雅的解决方案。
Private SubRunLoop()
  While loops >= 1 And Not bStopLoop
    ' my code that runs in the loop
    loop = loop - 1
    Application.DoEvents()
  End While
End Sub