Va bene riavviare un BackgroundWorker all'interno dell'evento Completato

0

Voglio che un lavoratore in background continui a funzionare e occasionalmente aggiorni l'interfaccia utente. La mia prima idea era usare un BackgroundWorker e nel suo evento completato è sufficiente accenderlo di nuovo.

L'utilizzo di un BackgroundWorker è accettabile in questo modo? o ci sono potenziali problemi nell'utilizzo dell'evento completato per attivare il lavoratore?

Di seguito c'è qualche pseudo codice di quali sono le mie intenzioni

class Program
{
    private static BackgroundWorker worker;
    private static Int32 runs = 0;

    static void Main(string[] args)
    {
        worker = new BackgroundWorker();
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.RunWorkerAsync(runs);
        Console.ReadLine();
    }

    static void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        //Do time consuming work
        Thread.Sleep(3000);
    }

    static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //Update the UI and start time consuming work again
        runs++;
        Console.WriteLine("Completed run #" + runs);
        worker.RunWorkerAsync();
    }
}
    
posta GER 28.08.2014 - 21:19
fonte

3 risposte

0

Non è assolutamente chiaro dalla specifica se un BackgroundWorker possa essere considerato ancora in esecuzione quando viene attivato l'evento RunWorkerCompleted - nel qual caso chiamare RunWorkerAsync () causerà un'eccezione.

Poiché la specifica non è chiara, non utilizzerei di nuovo l'oggetto BackgroundWorker: potrebbe funzionare o potrebbe rompersi su versioni diverse di .Net. Basta crearne uno nuovo nel gestore worker_RunWorkerCompleted ().

Se cerchi Riutilizzo di BackgroundWorker , troverai diversi post che suggeriscono che potrebbero esserci dei problemi in quest'area.

    
risposta data 28.08.2014 - 21:56
fonte
1

Utilizzare il Backgroundworker in questo modo non è accettabile. Ecco perché ha in particolare un evento ProgressChanged. Suggerirei di riscrivere la tua app per accettare un numero intero di MaxRuns e passare quella volta alla BGW. Quindi all'interno del loop di lavoro BGW su ogni corsa. In fondo a ogni corsa, quindi segnala lo stato di avanzamento.

So che il tuo esempio è abbreviato ed è un'app per console. Ma nel caso in cui tu abbia mai un'app per moduli, puoi impostare una barra di progresso da 0 a MaxRun e far riferire all'operatore di BGW il suo ritorno all'interfaccia utente, in modo che l'interfaccia utente possa spostare la barra di avanzamento.

Sull'ultimo suggerimento: la segnalazione dell'avanzamento ha un parametro denominato ProgressPercentage. È solo un int, che può essere negativo o > 100. Quindi non sentirti vincolato tra 0 e 100.

MODIFICA: codice di esempio

class Program

{     lavoratore statico di BackgroundWorker privato;     int32 maxRuns statico privato = 3333;

static void Main(string[] args)
{
    worker = new BackgroundWorker();
    worker.DoWork += worker_DoWork;
    worker.RunWorkerCompleted += worker_RunWorkerCompleted;
    worker.ProgressChanged += worker_ProgressChanged;
    worker.RunWorkerAsync(maxRuns);
    Console.ReadLine();
}

static void worker_DoWork(object sender, DoWorkEventArgs e)
{
    int totalRuns = (int)e.Argument;
    for (int i = 0; i < totalRuns; i++)
    {
        var sw = Stopwatch.StartNew();
        //Do time consuming work 
        Thread.Sleep(3000);
        worker.ReportProgress(i, sw.Elapsed);
    }
}

// This method runs in the foreground thread while the background worker is busy.
static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // e.ProgressPercentage is not a true percentage.  Rather it is the Run number.
    var percent = (100 * e.ProgressPercentage) / maxRuns;
    var elapsed = (TimeSpan)e.UserState;
    Console.WriteLine(string.Format("{0}% complete.  Run {1} of {2} took {3}.", percent, e.ProgressPercentage, maxRuns, elapsed));
}

static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    Console.WriteLine("Background Completed.");
}

}

    
risposta data 30.08.2014 - 17:31
fonte
0

se vuoi semplicemente riavviarlo immediatamente, sembrerebbe un'opzione migliore per avvolgere il corpo della funzione DoWork in un ciclo infinito.

    
risposta data 30.08.2014 - 17:31
fonte

Leggi altre domande sui tag