I’m seeing some strange behavior where the RunWorkerCompleted event for one of two threads I start isn’t being called depending on how I call them. Check out the code below, and the two methods of firing the threads, good() and 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
In both cases the DoWork event is called for both threads. But in the bad() case, only the second thread fires the RunWorkerCompleted event. This is obviously due to the two different ways I’m using VB to handle events here. I’m looking for an explanation of this behavior, preferably with a link to some documentation that could help me understand how these events are being handled in VB better. It seems strange to me that just reusing a variable name here seems to either dispose of the thread before it’s done or else just make it stop firing events.
In the Visual Basic Language Specification, a document you can download from Microsoft. Chapter 9.6.2 “WithEvents Variables” says this:
The bolded phrase describes the behavior you see. It is rather important it works that way. If it didn’t then you could never unsubscribe from an event and the event subscriptions would pile on without limit.