[Vb.net 2010] Aiuto background worked

Sevenjeak

Utente Attivo
27 Nov 2012
80
2
8
31
sevenjeak.altervista.org
Premetto che non uso spesso il BackgroundWorked, ma sto provando, per un'altro mio programma, ad aggiornare, ogni secondo, la proprietà Text del form, con la data corrente, oltre a questo ho inserito alla chiusura del programma che: viene interrotto il lavoro in background e che lo stesso programma non viene chiuso ( solamente per ora ), il codice è questo:

Codice:
Private Sub mainForm_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        BackgroundWorker1.CancelAsync()
        e.Cancel = True
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        BackgroundWorker1.RunWorkerAsync()
    End Sub

    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        BackgroundWorker1.WorkerReportsProgress = True
        BackgroundWorker1.WorkerSupportsCancellation = True
        Dim i As Integer = 0

        While True
            System.Threading.Thread.Sleep(1)
            BackgroundWorker1.ReportProgress(i)

            If BackgroundWorker1.CancellationPending = True Then
                e.Cancel = True
            Else
                i += 1
            End If
        End While
    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        Me.Text = Now
    End Sub
Ora questo codice, mi deve visualizzare, nel titolo del form, l'ora in tempo reale, e fino qui tutto ok, ma, quando chiudo il form, il lavoro in background mi continua ( mi mostra sempre l'orario corrente, senza fermarsi ), sbaglio qualcosa io?
 

Vins

Moderatore
Membro dello Staff
MOD
28 Lug 2009
238
19
0
Prova a fare questo:

BackgroundWorker1.WorkerSupportsCancellation = true;
BackgroundWorker1.CancelAsync();
BackgroundWorker1.Dispose();
BackgroundWorker1= null;
 

Sevenjeak

Utente Attivo
27 Nov 2012
80
2
8
31
sevenjeak.altervista.org
Il WorkerSupportsCancellation = true; lo inserito nell'evento doWork(), cmq ho provato a scrivere cosi:

Codice:
BackgroundWorker1.CancelAsync()
        BackgroundWorker1.Dispose()
        BackgroundWorker1 = Nothing
        e.Cancel = True
Ma non funziona lo stesso, ora mi restituisce un NullReferenceException nell'evento doWork() nella linea, backgroundWorker1.reportProgress(i), credo che me lo faccia perché ho impostato a Nothing il backgroundWorker, mi restituisce questa eccezione: Object reference not set to an instance of an object.
 

Vins

Moderatore
Membro dello Staff
MOD
28 Lug 2009
238
19
0
E tu non puoi controllare che backgroundWorker1.reportProgress(i) sia diverso da null e in caso negativo non fare eseguire il codice?
 

Sevenjeak

Utente Attivo
27 Nov 2012
80
2
8
31
sevenjeak.altervista.org
Cioè, dovrei metterlo come condizione nel while, o altro, cosa intendi?
 

Vins

Moderatore
Membro dello Staff
MOD
28 Lug 2009
238
19
0
Si, una soluzione potrebbe essere questa.

Ma perchè il programma non deve essere chiuso?
 

Sevenjeak

Utente Attivo
27 Nov 2012
80
2
8
31
sevenjeak.altervista.org
Non c'è nessun motivo, quell''istruzione, e.cancel = true, che ovviamente non permette la chiudere il programma, lo messa solamente per verificare che l'istruzione sopra, che fermano il lavoro in background, venissero eseguite correttamente, solo per quello non faccio chiudere il programma, solo per verificare questo, infatti una volta che riesco il programma lo faccio chiudere.

Ora sto provando a modificare il codice come hai detto te, ti farò sapere.
 

Sevenjeak

Utente Attivo
27 Nov 2012
80
2
8
31
sevenjeak.altervista.org
Scusate se uppo ma non posso editare il mio precedente messaggio, cmq ho provato a modificare il while cosi:

Codice:
while BackgroundWorker1.ReportProgress(i) = Nullable
Ma mi segna sia BackgroundWorker1.ReportProgress(i) che Nullable in rosso.

Per ora sto provando a cercare la soluzione su internet ma non saprei come fare.
 

Vins

Moderatore
Membro dello Staff
MOD
28 Lug 2009
238
19
0
In tutti gli esempi che troverai vedrai che viene indicato il metodo CancelAsync() per terminare l'elaborazione.

Quello che succede a te dipende probabilmente dall'operazione di annullamento della chiusura del form, cioè l'e.cancel = true annulla pure la terminazione del backgroundworker.

Pertanto chiudendo il form tutto dovrebbe funzionare.
 

Sevenjeak

Utente Attivo
27 Nov 2012
80
2
8
31
sevenjeak.altervista.org
Guardando su internet mi sono ricordato del metodo CancellationPending, che verifica se è stato chiamato il metodo di CancelAsyns(), il metodo e.cancel = true non centra niente, il quando fa riferimento all'evento di chiusura del form, infatti, modificando il codice cosi:

Codice:
    Private Sub mainForm_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        BackgroundWorker1.CancelAsync()
        e.Cancel = True
    End Sub

    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim i As Integer = 0

        While BackgroundWorker1.CancellationPending <> True
            System.Threading.Thread.Sleep(1)

            BackgroundWorker1.ReportProgress(i)
            i += 1
        End While
    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        Me.Text = Now
    End Sub
Il codice funziona correttamente, ora posso anche togliere l'annullamento della chiusura, grazie per l'aiuto.
 

Vins

Moderatore
Membro dello Staff
MOD
28 Lug 2009
238
19
0
Io non ho detto che l' e.cancel = true c'entrasse direttamente con il backgroundworker, intendevo che annullando la chiusura del form alcune risorse potevano non essere rilasciate e dare problemi.

Se hai risolto così va bene, comunque anche controllare se BackgroundWorker1.ReportProgress(i) non ha valore nullo è una soluzione.