2011-09-13 2 views
23

Sono uno di quei programmatori casuali, quindi non ho tanta conoscenza sulla programmazione delle migliori pratiche.C# dovrei creare un lavoratore in background o molti?

Ho un'applicazione che attualmente utilizza 4 Background Worker.

Quindi io li dichiarano:

private BackgroundWorker bw1; 
private BackgroundWorker bw2; 
private BackgroundWorker bw3; 
private BackgroundWorker bw4; 

Poi configurarli:

bw1 = new BackgroundWorker(); 
bw1.WorkerReportsProgress = true; 
bw1.DoWork += new DoWorkEventHandler(bw1_DoWork); 
bw1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw1_RunWorkerCompleted); 
bw1.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged); 

bw2 = new BackgroundWorker(); 
bw2.WorkerReportsProgress = true; 
bw2.DoWork += new DoWorkEventHandler(bw2_DoWork); 
bw2.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw2_RunWorkerCompleted); 
bw2.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged); 

bw3 = new BackgroundWorker(); 
bw3.WorkerReportsProgress = true; 
bw3.DoWork += new DoWorkEventHandler(bw3_DoWork); 
bw3.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw3_RunWorkerCompleted); 
bw3.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged); 

bw4 = new BackgroundWorker(); 
bw4.WorkerReportsProgress = true; 
bw4.DoWork += new DoWorkEventHandler(bw4_DoWork); 
bw4.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw4_RunWorkerCompleted); 
bw4.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged); 

E allora io uso il bw1.RunWorkerAsync(), bw2.RunWorkerAsync(), e così via ...

La cosa è che non li chiamo mai contemporaneamente, sono chiamati in punti diversi in modo piuttosto lineare.

Quindi la mia domanda è: è meglio avere molti utenti in background "pre-configurati" o averne uno e modificare gli eventi DoWork ed RunWorkerCompleted in base a ciò che voglio che faccia?

+5

Se si utilizzano più operatori in background, è necessario inserirli in un 'Elenco ' per impedire il codice ridondante. In questo modo, se ne aggiungi altri dieci, non devi aggiungere dieci volte la quantità di codice. –

risposta

20

Da un punto di vista architettonico, è preferibile disporre di un worker in background separato per ogni attività in background, che non è logicamente correlato a un'altra attività della classe.

0

Fare l'elaborazione utilizzando BackgroundWorker significa che lo si fa in un thread separato. Quindi, se non hai bisogno di multithreading, non c'è bisogno di addetti ai lavori separati. Se attendi il completamento dopo l'avvio di ciascuno dei tuoi dipendenti, puoi avere un solo lavoratore. Potrebbe anche rimuovere parte della duplicazione del codice ...

4

In genere è ragionevole utilizzare più thread se è utile con un utilizzo più efficiente delle risorse sul sistema. Per le attività a uso intensivo della CPU, un thread per core della CPU è un buon punto di partenza. Per le attività intensive di IO, puoi sicuramente averne molte di più.

Se si dispone della flessibilità per l'utilizzo di .NET 4, analizzerei lo Task Parallel Library invece di BackgroundWorker. Per impostazione predefinita, prenderà decisioni relativamente intelligenti sul numero di thread da eseguire contemporaneamente oltre a fornire un modello di programmazione più semplice.

+0

Daremo un'occhiata a TPL, sto usando .NET 4. – Alex

+0

Grazie, cercherò anche di capire TPL più tardi. –

0

Si eseguono lavoratori per alcuni scopi computazionali. Se il calcolo di una chiamata viene utilizzato o dipende in un modo diverso da un altro, è possibile utilizzare più di un lavoratore, al fine di ottenere prestazioni migliori (dal modo in cui questo è troppo soggetto per la misurazione). Se hai solo bisogno di 4 lavori, e li esegui in un thread separato solo per non bloccare l'interfaccia utente principale, un lavoratore è una buona soluzione.

24

Di solito utilizzo gli addetti allo sfondo in uno schema abbastanza diverso. Invece di definirli tutti insieme all'inizio, inclusi i rispettivi gestori di eventi, li creo al volo quando faccio qualcosa che ne ha bisogno.

public void SomeEventHandlerMaybe(object sender, EventArgs e) { 
    // do something 

    var bw = new BackgroundWorker(); 
    bw.ReportsProgress = true; 
    bw.DoWork += delegate { 
    // do work. You can use locals from here 
    }; 
    bw.ProgressChanged += delegate { ... }; 
    bw.RunWorkerCompleted += delegate { 
    // do something with the results. 
    }; 
    bw.RunWorkerAsync(); 
} 

Qualcosa del genere. Ha il vantaggio di avere tutto il codice che fa qualcosa con o nel lavoratore in background in un posto e all'incirca nell'ordine giusto.

+2

Non ho pensato di crearli al volo, questa è una buona strada per me, grazie! – Alex

+0

+1 ....Questo approccio può salvare anche parte della memoria cache :) – Sandy

+0

Questo approccio consente di ReportProgress (i) in DoWork e ottenere ProgressPercent all'interno del delegato ProgressChanged? – Developr