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.
preguntado el 01 de febrero de 12 a las 22:02
Where is this automatic unsubscribing documented?
In the Visual Basic Language Specification, a document you can descargar de Microsoft. Chapter 9.6.2 "WithEvents Variables" says this:
The implicit property created by a WithEvents declaration takes care of hooking and unhooking the relevant event handlers. When a value is assigned to the variable, the property first calls the remove method for the event on the instance currently in the variable (unhooking the existing event handler, if any). Next the assignment is made, and the property calls the add method for the event on the new instance in the variable (hooking up the new event handler).
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.