BackGroundWorker RunWorkerCompleted事件有时不被调用

时间:2012-02-01 22:50:09

标签: vb.net multithreading backgroundworker

我看到一些奇怪的行为,我启动的两个线程之一的RunWorkerCompleted事件没有被调用,具体取决于我如何调用它们。查看下面的代码,以及触发线程的两种方法,good()和bad()。

Public Class Form1

  Private WithEvents bw As System.ComponentModel.BackgroundWorker
  Private WithEvents bw2 As System.ComponentModel.BackgroundWorker
  Private starts As Integer = 0

  Private Sub bw_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bw.DoWork
    starts += 1
    Threading.Thread.Sleep(e.Argument)
  End Sub

  Private Sub bw_Completed(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted
    MessageBox.Show("Ending " + starts.ToString())
  End Sub

  Private Sub bad()
    bw = New System.ComponentModel.BackgroundWorker()
    bw.RunWorkerAsync(5000)

    Threading.Thread.Sleep(500)

    bw = New System.ComponentModel.BackgroundWorker()
    bw.RunWorkerAsync(5)
  End Sub

  Private Sub good()
    bw2 = New System.ComponentModel.BackgroundWorker()
    AddHandler bw2.DoWork, AddressOf bw_DoWork
    AddHandler bw2.RunWorkerCompleted, AddressOf bw_Completed
    bw2.RunWorkerAsync(500)

    bw2 = New System.ComponentModel.BackgroundWorker()
    AddHandler bw2.DoWork, AddressOf bw_DoWork
    AddHandler bw2.RunWorkerCompleted, AddressOf bw_Completed
    bw2.RunWorkerAsync(5)
  End Sub

  Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    'good()
    bad()
  End Sub
End Class

在这两种情况下,都会为两个线程调用DoWork事件。但在bad()情况下,只有第二个线程触发RunWorkerCompleted事件。这显然是由于我使用VB处理事件的两种不同方式。我正在寻找这种行为的解释,最好是链接到一些文档,可以帮助我更好地理解如何在VB中处理这些事件。对我来说似乎很奇怪,只是在这里重用一个变量名称似乎要么在它完成之前处理该线程,要么只是让它停止触发事件。

1 个答案:

答案 0 :(得分:1)

  

这个自动取消订阅记录在哪里?

在Visual Basic语言规范中,您可以download from Microsoft创建一个文档。第9.6.2章“WithEvents变量”说明了这一点:

  

由WithEvents声明创建的隐式属性负责挂钩和取消挂钩相关的事件处理程序。将值赋给变量时,属性首先在当前变量中的实例上调用事件的remove方法(取消现有事件处理程序,如果有的话)。接下来进行赋值,并且属性为变量中的新实例上的事件调用add方法(连接新的事件处理程序)。

粗体短语描述了您看到的行为。它的工作方式非常重要。如果没有,那么你永远不能取消订阅一个事件,并且事件订阅将无限制地堆积。