Come raggirare le limitazioni del BackgroundWorker (VB.NET)

Guglielmo Cancelli 5 Punti di reputazione
2024-04-01T09:14:19.2366667+00:00

Sto scrivendo un'applicazione che effettua operazioni molto lunghe e molto pesanti e che nel mezzo, periodicamente aggiorna o legge l'interfaccia utente nel form.

Sono 1500 righe solo nel form e non è praticabile la riscrittura completa dell'applicazione.

Il problema è che inevitabilmente il form finisce in "non risponde" e ciò preoccupa gli utenti.

Come evito questo problema?


Usare un BackgroundWorker si è rivelata una pessima soluzione perchè in DoWork non posso accedere agli elementi del form.

Sia utilizzare Invoke sia ProgressChanged comporterebbe ovviamente la riscrittura di tutto il codice.


Application.DoEvents() non ha funzionato

VB
VB
Linguaggio di programmazione orientato agli oggetti sviluppato da Microsoft implementato in .NET Framework. Precedentemente noto come Visual Basic .NET.
13 domande
0 commenti Nessun commento
{count} voti

1 risposta

Ordina per: Più utili
  1. Monica Caprio (Convergys International Europe) 640 Punti di reputazione Fornitore Microsoft
    2024-04-01T12:40:21.8933333+00:00

    Gentile Guglielmo,

    Se non puoi riscrivere completamente l'applicazione e vuoi evitare il problema di "non risponde", una soluzione potrebbe essere quella di utilizzare un'architettura a thread multipli insieme all'uso di Invoke per aggiornare l'interfaccia utente in modo sicuro.

    Ecco come potresti procedere:

    1. Crea un thread separato per le operazioni lunghe: Sposta le operazioni lunghe in un thread separato per evitare il blocco dell'interfaccia utente principale. Questo ti consentirà di mantenere l'interfaccia utente responsiva durante l'esecuzione delle operazioni.
    2. Aggiorna l'interfaccia utente utilizzando Invoke: Quando hai bisogno di aggiornare l'interfaccia utente con i risultati delle operazioni lunghe, utilizza il metodo Invoke per eseguire il codice nell'interfaccia utente principale. In questo modo eviterai problemi di accesso concorrente.

    Ecco un esempio di come potresti implementare questa soluzione:

    
    Imports System.Threading
    
    Public Class Form1
    
        Private Sub btnStartLongOperation_Click(sender As Object, e As EventArgs) Handles btnStartLongOperation.Click
    
            Dim thread As New Thread(AddressOf LongOperation)
    
            thread.Start()
    
        End Sub
    
        Private Sub LongOperation()
    
            ' Simulazione di un'operazione lunga
    
            For i As Integer = 0 To 100
    
                ' Esegui l'operazione lunga
    
                Thread.Sleep(100) ' Simula il lavoro
    
                ' Aggiorna l'interfaccia utente in modo sicuro utilizzando Invoke
    
                UpdateUI("Progress: " & i & "%")
    
            Next
    
        End Sub
    
        Private Sub UpdateUI(ByVal message As String)
    
            ' Verifica se è necessario l'Invoke
    
            If Me.InvokeRequired Then
    
                Me.Invoke(Sub() UpdateUI(message))
    
            Else
    
                ' Aggiorna l'interfaccia utente
    
                lblStatus.Text = message
    
            End If
    
        End Sub
    
    End Class
    
    

    In questo esempio, quando viene premuto il pulsante per avviare l'operazione lunga, viene creato un nuovo thread (LongOperation) per eseguire l'operazione lunga. Il metodo UpdateUI viene utilizzato per aggiornare l'etichetta di stato (lblStatus) in modo sicuro utilizzando Invoke. Questo assicura che l'aggiornamento dell'interfaccia utente avvenga nel thread dell'interfaccia utente principale.

    Utilizzando questa tecnica, puoi mantenere l'interfaccia utente responsiva durante le operazioni lunghe senza dover riscrivere completamente l'applicazione.

    Spero di esserti stata utile.

    Monica.