168

Let's say I want to sent an int parameter to a background worker, how can this be accomplished?

private void worker_DoWork(object sender, DoWorkEventArgs e) {

}

I know when this is worker.RunWorkerAsync();, I don't understand how to define in worker_DoWork that it should take an int parameter.

sooprise
  • 22,657
  • 67
  • 188
  • 276

8 Answers8

265

You start it like this:

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

and then

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.
}
H H
  • 263,252
  • 30
  • 330
  • 514
107

Even though this is an already answered question, I'd leave another option that IMO is a lot easier to read:

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

And on the handler method:

private void WorkerDoWork(int value, string text) {
    ...
}
dcarneiro
  • 7,060
  • 11
  • 51
  • 74
  • 13
    I didnt know what IMO meant, I thought it was a C# thing. I googled "C# IMO" and landed here and got the answer...lol https://www.quantnet.com/threads/c-c-vba-or-java.11433/ – electricalbah Mar 06 '14 at 07:04
  • How about 3 parameters? – YukiSakura Oct 05 '15 at 09:01
  • I don't play with .NET since 2012, but if I'm not mistaken you can add the parameters you want `... => WorkerDoWork(a, b, c);` as long as it matches the method signature `... WorkerDoWork(int a, string b, string c) {...` – dcarneiro Oct 05 '15 at 14:09
  • 1
    Keep in mind if you used this (like I tried to do), you have to create a new backgroundworker each time (in your example you did). Else you will have an issue like I did. My backgroundworker would keep repeating the previous runs. If run once it was fine. 2 times it repeated last run and current run. 3rd run would repeat last two and current. etc. – B. Shea Dec 28 '16 at 03:34
  • But how does the value get passed into RunWorkerAsync? – CodyBugstein May 03 '19 at 16:38
55

You can pass multiple arguments like this.

List<object> arguments = new List<object>();
arguments.Add("first");      //argument 1
arguments.Add(new Object()); //argument 2
// ...
arguments.Add(10);           //argument n

backgroundWorker.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. 
}
Seraphim's
  • 12,559
  • 20
  • 88
  • 129
Zain Ali
  • 15,535
  • 14
  • 95
  • 108
  • @missReclusive cast the "genericlist" items,i.e,Let say "argument 1" is of type int then int argument1=(int)genericlist[0] – Zain Ali May 06 '14 at 14:36
  • 2
    this is a bad idea in terms of maintenance. You should use concrete types over List because at least you'll be able to figure out what you were doing (see an example in my answer below) – Denis Mar 12 '15 at 13:46
  • I'd probably prefer a `Tuple` (or a specialised class) rather than a list of generic objects – James S Mar 17 '15 at 15:02
9

You can use the DoWorkEventArgs.Argument property.

A full example (even using an int argument) can be found on Microsoft's site:

Dave Mateer
  • 17,608
  • 15
  • 96
  • 149
7

you can try this out if you want to pass more than one type of arguments, first add them all to an array of type Object and pass that object to RunWorkerAsync() here is an example :

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

Now in the doWork method of background worker

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
  • 681
  • 1
  • 8
  • 23
  • 2
    +1 . Sending the arguments in this manner also avoids having to start a New backgroundworker each run to avoid repeats. (at least in my app). See my comment below related to this problem. Also http://stackoverflow.com/a/12231431/503621 & http://stackoverflow.com/questions/12507602/c-sharp-backgroundworker-keep-on-running-dowork – B. Shea Dec 28 '16 at 03:42
  • My casting failed `_dirs = (string[])e.Argument;` but this `_dirs = e.Argument as string[];` functions. The casting tried to cast to an Interface, and code complied... Many thanks! – Marcelo Scofano Diniz Nov 14 '20 at 23:29
7

Check out the 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;
    }
}
Jay Riggs
  • 53,046
  • 9
  • 139
  • 151
5

You need RunWorkerAsync(object) method and DoWorkEventArgs.Argument property.

worker.RunWorkerAsync(5);

private void worker_DoWork(object sender, DoWorkEventArgs e) {
    int argument = (int)e.Argument; //5
}
alpha-mouse
  • 4,953
  • 24
  • 36
4

You should always try to use a composite object with concrete types (using composite design pattern) rather than a list of object types. Who would remember what the heck each of those objects is? Think about maintenance of your code later on... Instead, try something like this:

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

And then:

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

and then:

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
  • 11,796
  • 16
  • 88
  • 150