【问题标题】:VB.Net Pausing and Resuming For-NextVB.Net 暂停和恢复 For-Next
【发布时间】:2014-12-14 04:19:22
【问题描述】:

我有以下代码(VB.Net),它完全符合我的要求(即在代码的特定间隔/位置暂停并在单击消息框按钮时恢复)...... 唯一的问题是我使用了一个消息框;有没有办法用按钮代替做同样的工作?没有计时器,没有消息框?

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim Index As Integer
    For KKK = 1 To 50
        Index = KKK / 5
        If Index = KKK / 5 Then
            MessageBox.Show("Paused at: " & KKK & " : Click OK to Resume")
        End If
    Next
End Sub

提前感谢 cmets 和帮助。

【问题讨论】:

    标签: vb.net visual-studio-2010


    【解决方案1】:

    如果您升级到 VS2013 Community(免费),那么您可以像这样使用 Async/Await 组合:

    Public Class Form1
    
        Private MRE As New Threading.ManualResetEvent(False)
    
        Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Button1.Enabled = False
            Button2.Enabled = False
    
            For KKK = 1 To 50
                If KKK Mod 5 = 0 Then
                    Label1.Text = KKK
                    MRE.Reset()
                    Button2.Enabled = True
                    Await WaitForButton()
                End If
            Next
    
            Button1.Enabled = True
        End Sub
    
        Private Function WaitForButton() As Task
            Return Task.Run(Sub()
                                MRE.WaitOne()
                            End Sub)
        End Function
    
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            Button2.Enabled = False
            MRE.Set()
        End Sub
    
    End Class
    

    【讨论】:

    • 我必须承认您的解决方案非常有效。在 Visual Studio 2012 Ultimate 中测试。
    • Async/Await 最初是在 VS2012 中引入的,所以这将是您可以使用的最旧版本。
    • 感谢 Idle_Mind;我尝试了几天来进行此更新;我会弄清楚的......非常感谢cmets和回答;我以前用过你对其他成员的回答,它们非常有用……我认识你……干杯。
    【解决方案2】:

    需要 2 个按钮和一个标签。试试这个:

    Dim Pause As Boolean    
    
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Dim Index As Integer
        Pause = False
        Button2.Text = "Ok"
        Button2.Enabled = False
        For KKK = 1 To 50
            System.Threading.Thread.Sleep(250) 'Just for testing purposes, do not use this instruction.
            Index = KKK / 5
            If Index = KKK / 5 Then
                Label1.Text = "Paused at: " & KKK & " : Click OK to Resume"
                Pause = True
                Button2.Enabled = True
                Button2.Focus()
                While Pause
                    Application.DoEvents()
                End While
                Label1.Text = ""
                Button2.Enabled = False
            End If
        Next
    End Sub
    
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Pause = False
    End Sub
    

    【讨论】:

    • 这应该可以,但我认为 CPU 负载可能会在 While 循环中达到峰值。
    • 嗨天空大师;我正在尝试代码,但它似乎没有完成这项工作?我仍在努力让它发挥作用,但我明白了你的想法;我同意你在 CPU 问题上的看法;你知道 Messagebox 如何在不影响 CPU 的情况下完成这项工作吗?
    • CPU 的问题很小。 DoEvents() 方法处理消息队列中的所有消息。
    • @Abbas1999 固定代码。但是,这比消息框要好,消息框是一个模式窗口,在您按确定之前不允许执行任何操作。在第一代 Corei3 上测试,CPU 消耗并不重要。
    • 一个单核系统,While 循环会将其固定为 100%。在双核系统上,它将是 50%。您拥有的核心越多,它似乎产生的影响就越小。如果这是一个问题,只需在循环中放置一个对 Sleep() 的 small 调用。 Sleep(10) 足以显着减少使用量。
    【解决方案3】:

    您可以通过将循环放入一个单独的线程中,为暂停而休眠,并通过单击按钮来中断它来做到这一点。在本例中,button1 启动循环,而 button2 在thread.sleep 中断它。

    Dim newThread As New Thread(AddressOf loopSub)
    Delegate Sub textAddCallback(ByVal s As string)
    
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    newThread.Start()
    End Sub
    
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    newThread.Interrupt()
    End Sub
    
    Sub loopSub()
      Dim Index As Integer
      Dim textDelegate As New textAddCallback(AddressOf textAdd)
    
      Try
          For KKK As Integer = 1 To 50
              Index = KKK / 5
              If Index = KKK / 5 Then
                  Thread.Sleep(36000) ' sleep the max amount of milliseconds
              End If
          Next
      Catch ex As ThreadInterruptedException
          Me.Invoke(textDelegate, "string to add")
      End Try
    
    End Sub
    
    Sub textAdd(ByVal s As String)
    rtext1.text &= s
    End Sub
    

    【讨论】:

    • 你好 xpda;非常感谢...我正在尝试测试您的代码,但它不允许我在 Sub loopSub() 内的 RichTextBox 中附加文本,因为它位于单独的线程中......我在里面使用 RichTextBox For-Next 循环原本......有没有办法做到这一点?
    • 是的,这有点乱,但是您可以使用调用委托。我会在答案中添加(未经测试,但你会明白的)。
    • 感谢 xpda 的努力,我的代码仍然有问题;我想知道消息框是如何完成这项工作的?
    猜你喜欢
    • 2016-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-19
    • 2015-07-28
    • 2014-12-03
    • 1970-01-01
    相关资源
    最近更新 更多