BackGroundWorker RunWorkerCompleted Evento no llamado a veces

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

Usted está Sustitución the reference to the BackgroundWorker mientras it is running. So sure, the events attached to that reference through WithEvents get unsubscribed. By design. -

How is it different from what I'm doing when I add handlers? I'm replacing that reference as well, but events don't get unsubscribed. Is this design documented anywhere? -

Because that object reference isn't declared with WithEvents so the automatic unsubscribing doesn't happen. -

Where is this automatic unsubscribing documented? I understand that it is happening, but it seems like a very strange behavior to me. -

I am not that familiar with VB (I am mostly C#), but I fail to see how this code does what you say it does - bw_DoWork() y bw_Completed() are not connected to `bw`` after it is instantiated at all in bad() so how can that code run at all? -

1 Respuestas

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.

Respondido 03 Feb 12, 04:02

Thanks for the link and the reasoning. Exactly what I was looking for. - user12861

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.