2009-07-17 4 views
32

L'oggetto BackgroundWorker ci consente di passare un singolo argomento in DoWorkEventHandler.Alternativa a BackgroundWorker che accetta più di un argomento?

// setup/init: 
BackgroundWorker endCallWorker = new BackgroundWorker(); 
endCallWorker.DoWork += new DoWorkEventHandler(EndCallWorker_DoWork); 
... 
endCallWorker.RunWorkerAsync(userName); 

// the handler: 
private void EndCallWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    string userName = e.Argument as string; 
    ... 
} 

passare più argomenti, io devo avvolgere in un oggetto, in questo povero array di stringhe:

// setup/init: 

BackgroundWorker startCallWorker = new BackgroundWorker(); 
startCallWorker.DoWork += new DoWorkEventHandler(StartCallWorker_DoWork); 
... 
startCallWorker.RunWorkerAsync(new string[]{userName, targetNumber}); 


// the handler: 
private void StartCallWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    string[] args = e.Argument as string[]; 
    string userName = args[0]; 
    string targetNumber = args[1]; 
} 

C'è un altro oggetto o modello che ci permette di passare più argomenti bene, o idealmente, scrivi la nostra firma?

risposta

45

Si potrebbe utilizzare una chiusura (lambda):

backgroundWorker.DoWork += (s, e) => MyWorkMethod(userName, targetNumber); 

O con delega (metodo anonimo) sintassi:

backgroundWorker.DoWork += 
    delegate(object sender, DoWorkEventArgs e) 
    { 
     MyWorkMethod(userName, targetNumber); 
    }; 
+0

potrebbe elaborare su come funziona? (in particolare "(s, e)" ... perché vengono dichiarati?) –

+0

Mi piace molto - Per il mio caso d'uso, funziona benissimo, ma le app più complesse potrebbero avere problemi, cioè ho bisogno di accedere al parametro valori (username e targetNumber) a setup/init. –

+1

Felice di aiutare (e qualche altro testo). –

0

Perché non passare l'oggetto "uno" è un array di parametri? Hai solo bisogno di tornare indietro alla matrice all'interno del metodo dal parametro oggetto.

2

passare Forse una funzione lambda come il vostro oggetto? Quindi lo chiameresti nel gestore di DoWork.

endCallWorker.RunWorkerAsync(new Action(() => DelegatedCallTarget(userName, targetNumber))); 
+0

potresti mostrarmi come faccio a scartarli nel gestore? –

3

L'oggetto può essere una lista o matrice o alcuni di questi. Trasforma il tuo oggetto in un contenitore di qualche tipo, quindi esegui il cast all'interno di BackgroundWorker. Devi però assicurarti di passare sempre dello stesso tipo.

+0

+ McAden Se i progettisti della libreria gestivano due argomenti, perché non tre, quattro, ecc.? La soluzione era gestirne una, e quella può essere un oggetto di complessità arbitraria. – DougN

12

Cosa c'è di sbagliato nell'usare un oggetto digitato?

internal class UserArgs 
{ 
    internal string UserName { get; set; } 
    internal string TargetNumber { get; set; } 
} 

var args = new UserArgs() {UserName="Me", TargetNumber="123" }; 
startCallWorker.RunWorkerAsync(args); 
+0

Questo è più bello della mia stringa [], ma ancora - Non voglio dichiarare un'altra classe solo per passare argomenti nella mia funzione. Questo accade in molti altri gestori incorporati in .NET. Penso che cerco uno schema coerente che non inquini il mio codice con classi wrapper inutili. –

+2

C# 4.0 ha una tupla che può contenere più di un arg. Si prega di fare riferimento alla mia risposta a questa domanda. –

4

anziché un oggetto digitato. C# 4.0 ci fornisce la tupla. Potremmo usare una tupla per contenere più argomenti. Quindi non è necessario dichiarare una nuova classe.

1

Creare una classe che contiene tutti i tuoi argomenti

Class MyClass 
{ 
    private string m_Username = string.Empty; 
    private int m_Targetnumber; 

    public MyClass(){} 

    public string Username 
    { 
     get { return m_Username; } 
     set { m_Username = value; } 
    } 

    public int TargetNumber 
    { 
     get { return m_TargetNumber; } 
     set { m_TargetNumber = value; } 
    } 
} 



// setup/init: 

BackgroundWorker startCallWorker = new BackgroundWorker(); 
startCallWorker.DoWork += new DoWorkEventHandler(StartCallWorker_DoWork); 
... 

MyClass thisClass = new MyClass(); 
thisClass.Username = "abcd"; 
thisClass.TargetNumber = 1234; 
startCallWorker.RunWorkerAsync(thisClass); 


// the handler: 
private void StartCallWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    MyClass args = (MyClass)e.Argument; 
    string userName = args.Username; 
    string targetNumber = args.TargetNumber; 
}