2011-01-26 5 views
115

Diciamo che voglio inviare un parametro int a un lavoratore in background, come può essere realizzato?Invio di argomenti al lavoratore in background?

private void worker_DoWork(object sender, DoWorkEventArgs e) { 

} 

so quando questo è worker.RunWorkerAsync() ;, Non capisco come definire in worker_DoWork che dovrebbe prendere un parametro int.

risposta

192

Si inizia così:

int value = 123; 
bgw1.RunWorkerAsync(value); // argument: value, the int will be boxed 

e poi

private void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    int value = (int) e.Argument; // the 'argument' parameter resurfaces here 

    ... 

    // and to transport a result back to the main thread 
    double result = 0.1 * value; 
    e.Result = result; 
} 


// the Completed handler should follow this pattern 
// for Error and (optionally) Cancellation handling 
private void worker_Completed(object sender, RunWorkerCompletedEventArgs e) 
{ 
    // check error, check cancel, then use result 
    if (e.Error != null) 
    { 
    // handle the error 
    } 
    else if (e.Cancelled) 
    { 
    // handle cancellation 
    } 
    else 
    {   
     double result = (double) e.Result; 
     // use it on the UI thread 
    } 
    // general cleanup code, runs when there was an error or not. 
} 
+27

Come posso fare due argomenti ? – sooprise

+3

Oppure invio un oggetto pieno di più di un argomento? – sooprise

+19

@soo: utilizzare una classe helper o una 'Tupla ' (C# 4 +) (Modifica: Sì, utilizzare un oggetto per comprimere tutto. Vedere ad esempio DoWorkEventArgs self). –

5

Scopri i DoWorkEventArgs.Argument Property:

... 
backgroundWorker1.RunWorkerAsync(yourInt); 
... 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    // Do not access the form's BackgroundWorker reference directly. 
    // Instead, use the reference provided by the sender parameter. 
    BackgroundWorker bw = sender as BackgroundWorker; 

    // Extract the argument. 
    int arg = (int)e.Argument; 

    // Start the time-consuming operation. 
    e.Result = TimeConsumingOperation(bw, arg); 

    // If the operation was canceled by the user, 
    // set the DoWorkEventArgs.Cancel property to true. 
    if (bw.CancellationPending) 
    { 
     e.Cancel = true; 
    } 
} 
83

Anche se questa è una domanda già risposto, avrei lasciato un'altra opzione che IMO è molto più facile da leggere:

BackgroundWorker worker = new BackgroundWorker(); 
worker.DoWork += (obj, e) => WorkerDoWork(value, text); 
worker.RunWorkerAsync(); 

E sul metodo del gestore :

private void WorkerDoWork(int value, string text) { 
    ... 
} 
+8

Non sapevo cosa intendesse IMO, pensavo fosse una cosa di C#. Ho cercato su google "C# IMO" e sono arrivato qui e ho ottenuto la risposta ... lol https://www.quantnet.com/threads/c-c-vba-or-java.11433/ – electricalbah

+0

Come circa 3 parametri? – YukiSakura

+0

Non gioco con .NET dal 2012, ma se non sbaglio puoi aggiungere i parametri che vuoi '... => WorkerDoWork (a, b, c);' finché corrisponde alla firma del metodo '... WorkerDoWork (int a, stringa b, stringa c) {...' – dcarneiro

36

È possibile passare più argomenti come questo.

List<object> arguments = new List<object>(); 
        arguments.Add(argument 1); 
        arguments.Add(argument 1); 
        arguments.Add(argument n); 


        backgroundWorker2.RunWorkerAsync(arguments); 

private void worker_DoWork(object sender, DoWorkEventArgs e) { 

    List<object> genericlist = e.Argument as List<object>; 
    extract your multiple arguments from this list and cast them and use them. 

} 
+1

come estrarre più argomenti dal codice precedente per favore aiuto .. – missReclusive

+0

@missReclusive lancia il" genericlista " elementi, per esempio, diciamo che "argomento 1" è di tipo int quindi int argument1 = (int) genericlist [0] –

+1

questa è una cattiva idea in termini di manutenzione. Dovresti usare i tipi di calcestruzzo sopra l'elenco perché almeno sarai in grado di capire cosa stavi facendo (vedi un esempio nella mia risposta di seguito) – Denis

4

si può provare questo se si desidera passare più di un tipo di argomenti, in primo luogo a tutti di aggiungere una matrice di tipo Object e passare tale oggetto da RunWorkerAsync() Ecco un esempio:

some_Method(){ 
    List<string> excludeList = new List<string>(); // list of strings 
    string newPath ="some path"; // normal string 
    Object[] args = {newPath,excludeList }; 
      backgroundAnalyzer.RunWorkerAsync(args); 
     } 

Ora nel metodo DoWork sfondo lavoratore

backgroundAnalyzer_DoWork(object sender, DoWorkEventArgs e) 
     { 
     backgroundAnalyzer.ReportProgress(50); 
     Object[] arg = e.Argument as Object[]; 
     string path= (string)arg[0]; 
     List<string> lst = (List<string>) arg[1]; 
     ....... 
     // do something...... 
     //..... 
     } 
+0

+1. L'invio degli argomenti in questo modo evita anche di dover avviare un nuovo Backgroundworker ogni volta per evitare ripetizioni. (almeno nella mia app). Vedi il mio commento qui sotto relativo a questo problema. Anche http://stackoverflow.com/a/12231431/503621 e http://stackoverflow.com/questions/12507602/c-sharp-backgroundworker-keep-on-running-dowork – bshea

4

Si dovrebbe sempre cercare di usare un oggetto composto di tipi concreti (utilizzando il modello di progettazione composito), piuttosto che una lista di oggetti t IPI. Chi si ricorderebbe che diamine fosse ciascuno di quegli oggetti? Pensate manutenzione del codice in seguito ... Invece, provare qualcosa di simile:

Public (Class or Structure) MyPerson 
       public string FirstName { get; set; } 
       public string LastName { get; set; } 
       public string Address { get; set; } 
       public int ZipCode { get; set; } 
End Class 

E poi:

Dim person as new MyPerson With { .FirstName = “Joe”, 
            .LastName = "Smith”, 
            ... 
           } 
backgroundWorker1.RunWorkerAsync(person) 

e poi:

private void backgroundWorker1_DoWork (object sender, DoWorkEventArgs e) 
{ 
     MyPerson person = e.Argument as MyPerson 
     string firstname = person.FirstName; 
     string lastname = person.LastName; 
     int zipcode = person.ZipCode;         
}