【问题标题】:Threading. How does button click interrupt/influence program flow穿线。按钮单击如何中断/影响程序流程
【发布时间】:2013-10-17 17:38:58
【问题描述】:

我的项目是vb.net 2010 windows桌面形式。 到目前为止,单线程(默认)。

如果 SUB 例程中有一个正在运行的 for...next 循环,如果触发了 buttonclick 事件并且在该事件中更改了变量,会发生什么情况?比如:程序执行是否离开了正在运行的循环?还是在 buttonclick 事件更改该变量时继续运行?

我的目标是: 如果有人单击该按钮,则 blnRequestStop 设置为 True。 在 for...next 循环中,就在“next”之前,它检查 blnRequestStop。如果为真则退出“for”循环。

我猜我需要使用线程?谁能给我一个简单的例子,好吗?

编辑: 下面的这段代码似乎工作正常。但也许你们都看到了问题?

If (btnProcess.Text = "Done!") Then
    End
ElseIf (btnProcess.Text = "IMPORT") Then
    bRequestStop = False
    t1 = New Thread(AddressOf ProcessDo)
    t1.Start()
Else
    t2 = New Thread(AddressOf MyInterrupt)
    t2.Start()
End If

下面是 ProcessDo 和 MyInterrupt 的简短版本:

Private Sub ProcessDo()
    For each X in blahblah
        'do stuff (yes, includes interface)
        if (blnInterrupt) then exit For
    Next X
    End
End Sub

Private Sub MyInterrupt()
    blnInterrupt=true
End Sub

【问题讨论】:

  • 听起来你在 UI 线程中有一个长时间运行的任务。基本上你不应该那样做......
  • 当您单击一个按钮时,所发生的只是事件排队(不是立即运行)。一旦您的 GUI 线程(您的 Form 所在的线程是 new Form("form1")'d 可用(空闲),那么它将读取队列并运行您的按钮单击事件。您的 GUI 线程将不会空闲,直到它退出 For ...下一个 SUB(我习惯了 C#,否则我会用代码回答)。看看这个msdn.microsoft.com/en-us/library/…

标签: vb.net multithreading winforms


【解决方案1】:

是的,您可能想在后台线程上执行长时间运行的任务。这是一个代码示例,包括在完成后如何将结果返回给 UI 线程(否则您将收到有关 Cross-thread operation not valid 的错误)。

ThreadPool 是在后台线程上做一些工作的好方法。您可以在停止按钮的按钮单击事件中设置stopIt = True

ThreadPool.QueueUserWorkItem(
  Sub()
    For Each thing In things
      If stopIt Then Exit Sub
      'Do the stuff!
    Next

    'We're done, update UI
    Me.UpdateUI("All done!")
  End Sub)

要安全地更新 UI,您需要确保回到 UI 线程。

Public Sub UpdateUI(result As String)
  If Me.InvokeRequired() Then 
    'If we aren't on the UI thread, invoke this function on the UI thread
    Me.BeginInvoke(Sub() UpdateUI(result))
    Exit Sub
  End If

  'Update UI here
  lblResult.Text = result
End Sub

【讨论】:

  • 请查看已编辑的原始问题。我想要你对我的代码的想法。
  • 我不熟悉直接使用Threads,我想说通常人们会推荐再次使用它们。使用ThreadPoolBackgroundWorker 通常会更好。这也取决于ProcessDoMyInterrupt 在做什么。如果他们在任何时候更新 UI,他们将需要返回 UI 线程。即使没有,您也可能需要执行Thread.Join(或类似的操作),以便在完成后关闭它们,但同样...我不熟悉Thread
【解决方案2】:

执行是'停止'(在某种程度上)直到循环完成他的工作,所以是的,你需要多线程。

这不是一个很长的操作,您需要在循环期间更新 UI 控件,然后您可以在循环内使用 Application.DoEvents 以便能够在 FOR 循环时在应用程序中正常使用其他控件工作,但我建议您这将对 UI 性能产生负面影响,但如果它不是一个持续时间较长的循环,那么您可能会考虑使用DoEvents 而不是引入multi-threading 这只是一种替代方案,不推荐但是,你可以使用它。

PS:原谅我的英语

【讨论】:

  • 永远不要将 DoEvents 用作正常程序流程的一部分......永远。请改用正确的线程。
  • 调用此方法会导致当前线程暂停,同时处理所有等待窗口消息。如果消息导致事件被触发,那么您的应用程序代码的其他区域可能会执行。这可能会导致您的应用程序出现难以调试的意外行为。如果您执行需要很长时间的操作或计算,通常最好在新线程上执行这些操作。有关异步编程的更多信息,请参阅异步编程模型 (APM)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多