Mengirim Argumen ke Pekerja Latar Belakang?

147

Katakanlah saya ingin mengirim parameter int ke pekerja latar belakang, bagaimana ini bisa dilakukan?

private void worker_DoWork(object sender, DoWorkEventArgs e) {

}

Saya tahu ketika ini adalah worker.RunWorkerAsync () ;, Saya tidak mengerti bagaimana mendefinisikan di worker_DoWork bahwa itu harus mengambil parameter int.

sooprise
sumber

Jawaban:

235

Anda memulainya seperti ini:

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

lalu

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.
}
Henk Holterman
sumber
38
Bagaimana saya bisa melakukan dua argumen?
sooprise
3
Atau apakah saya mengirim objek yang penuh dengan lebih dari satu argumen?
sooprise
23
@soo: Gunakan kelas pembantu atau Tuple<A,B>(C # 4 +) (Edit: Ya, gunakan objek untuk mengemas semuanya. Lihat misalnya DoWorkEventArgs sendiri).
Henk Holterman
Tetapi bagaimana Anda memberi tahu UI tentang hasilnya?
rayray
1
@rayray:, di label1.Text = e.Result.ToString();mana pun saya menandai itu sebagai aman.
Henk Holterman
102

Meskipun ini adalah pertanyaan yang sudah dijawab, saya akan meninggalkan opsi lain bahwa IMO jauh lebih mudah dibaca:

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

Dan pada metode handler:

private void WorkerDoWork(int value, string text) {
    ...
}
dcarneiro
sumber
12
Saya tidak tahu apa artinya IMO, saya pikir itu adalah hal C #. Saya googled "C # IMO" dan mendarat di sini dan mendapat jawabannya ... lol quantnet.com/threads/cc-vba-or-java.11433
electricbah
Bagaimana dengan 3 parameter?
YukiSakura
Saya tidak bermain dengan .NET sejak 2012, tetapi jika saya tidak salah, Anda dapat menambahkan parameter yang Anda inginkan ... => WorkerDoWork(a, b, c); asalkan cocok dengan metode signature... WorkerDoWork(int a, string b, string c) {...
dcarneiro
1
Perlu diingat jika Anda menggunakan ini (seperti yang saya coba lakukan), Anda harus membuat backgroundworker baru setiap kali (dalam contoh Anda melakukannya). Lain Anda akan memiliki masalah seperti yang saya lakukan. Pekerja latar belakang saya akan terus mengulangi menjalankan sebelumnya. Jika dijalankan sekali itu baik-baik saja. 2 kali mengulangi menjalankan terakhir dan saat ini berjalan. 3 run akan mengulangi dua terakhir dan saat ini. dll
bshea
Tapi bagaimana nilai bisa diteruskan ke RunWorkerAsync?
CodyBugstein
47

Anda dapat memberikan beberapa argumen seperti ini.

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. 

}
Zain Ali
sumber
@missReclusive melemparkan item "genericlist", yaitu, Katakanlah "argumen 1" adalah tipe int maka int argument1 = (int) genericlist [0]
Zain Ali
1
ini adalah ide yang buruk dalam hal pemeliharaan. Anda harus menggunakan tipe konkret di Daftar <object> karena setidaknya Anda akan dapat mengetahui apa yang Anda lakukan (lihat contoh dalam jawaban saya di bawah)
Denis
Saya mungkin lebih suka Tuple(atau kelas khusus) daripada daftar objek generik
James S
9

Anda bisa menggunakan DoWorkEventArgs.Argumentproperti.

Contoh lengkap (bahkan menggunakan argumen int) dapat ditemukan di situs Microsoft:

Dave Mateer
sumber
6

Check out DoWorkEventArgs.Argument Properti :

...
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;
    }
}
Jay Riggs
sumber
5

Anda dapat mencoba ini jika Anda ingin mengirimkan lebih dari satu jenis argumen, pertama-tama tambahkan semuanya ke array bertipe Objek dan meneruskan objek itu ke RunWorkerAsync () di sini adalah contoh:

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

Sekarang dalam metode pekerja latar belakang doWork

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......
        //.....
       }
sujay
sumber
2
+1. Mengirim argumen dengan cara ini juga menghindari keharusan memulai pekerja latar baru untuk menjalankan setiap pengulangan untuk menghindari pengulangan. (setidaknya di aplikasi saya). Lihat komentar saya di bawah terkait dengan masalah ini. Juga stackoverflow.com/a/12231431/503621 & stackoverflow.com/questions/12507602/…
bshea
4

Anda harus selalu mencoba menggunakan objek komposit dengan jenis beton (menggunakan pola desain komposit) daripada daftar jenis objek. Siapa yang akan ingat apa sih masing-masing benda itu? Pikirkan tentang pemeliharaan kode Anda nanti ... Alih-alih, coba sesuatu seperti ini:

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

Lalu:

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

lalu:

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;                                 
}
Denis
sumber