バックグラウンドワーカーに引数を送信しますか?


147

intパラメータをバックグラウンドワーカーに送信したいとします。これはどのようにして実現できますか?

private void worker_DoWork(object sender, DoWorkEventArgs e) {

}

これがworker.RunWorkerAsync();である場合はわかっていますが、worker_DoWorkでintパラメータを取る必要があることを定義する方法がわかりません。

回答:


235

次のように開始します。

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

その後

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.
}

38
どうすれば2つの引数を実行できますか?
sooprise

3
または、複数の引数でいっぱいのオブジェクトを送信しますか?
sooprise

23
@soo:ヘルパークラスまたはTuple<A,B>(C#4 +)を使用します(編集:はい、オブジェクトを使用してすべてをパックします。たとえば、DoWorkEventArgsセルフを参照してください)。
Henk Holterman、2011年

しかし、UIに結果をどのように通知しますか?
rayray

1
@rayray:、label1.Text = e.Result.ToString();どこでも安全だとマークしました。
Henk Holterman、

101

これは既に回答済みの質問ですが、IMOの方が読みやすいという別のオプションを残しておきます。

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

そして、ハンドラメソッドで:

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

12
IMOの意味がわかりませんでした。C#だと思いました。私は「IMO C#」をGoogleで検索してここに上陸したとの回答を得ました...笑 quantnet.com/threads/cc-vba-or-java.11433
electricalbah

3つのパラメータはどうですか?
YukiSakura、2015年

私は2012年以来.NETで遊んでいませんが... => WorkerDoWork(a, b, c);、メソッドのシグネチャと一致している限り、私が間違っていない場合は、必要なパラメーターを追加できます ... WorkerDoWork(int a, string b, string c) {...
dcarneiro

1
これを使用した場合は(私がやろうとしたように)、毎回新しいバックグラウンドワーカーを作成する必要があります(この例の場合)。そうでなければ、あなたは私がしたような問題を抱えているでしょう。私のバックグラウンドワーカーは以前の実行を繰り返し続けます。一度走れば大丈夫でした。最後の実行と現在の実行を2回繰り返しました。3回目の実行では、最後の2回と現在の繰り返しになります。など
bshea 16

しかし、値はどのようにRunWorkerAsyncに渡されるのでしょうか。
CodyBugstein

47

このように複数の引数を渡すことができます。

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. 

}

@missReclusiveは "genericlist"項目をキャストします。つまり、 "argument 1"の型がintで、次にint argument1 =(int)genericlist [0]
Zain Ali

1
これはメンテナンスの面で悪い考えです。List <object>では具象型を使用する必要があります。少なくとも、自分が何をしていたかを理解できるからです(以下の私の回答の例を参照)
Denis

私はおそらく好むTupleむしろ汎用オブジェクトのリストよりも(または特殊クラス)
ジェームズ・S


6

DoWorkEventArgs.Argumentプロパティを確認してください。

...
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;
    }
}

5

複数のタイプの引数を渡したい場合は、これを試して、最初にすべてをObject型の配列に追加し、そのオブジェクトをRunWorkerAsync()に渡すことができます。次に例を示します。

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

バックグラウンドワーカーの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......
        //.....
       }

2
+1。この方法で引数を送信すると、繰り返しを避けるために、実行ごとに新しいバックグラウンドワーカーを起動する必要がなくなります。(少なくとも私のアプリでは)。この問題に関する以下の私のコメントを参照してください。また、stackoverflow.com /
a / 12231431/503621


4

オブジェクトタイプのリストではなく、(複合デザインパターンを使用して)具体的なタイプの複合オブジェクトを常に使用するようにしてください。これらのオブジェクトのそれぞれが一体何であるかを誰が覚えているでしょうか?後でコードのメンテナンスについて考えてください...代わりに、次のようなことを試してください:

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

その後:

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

その後:

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;                                 
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.