170

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.

8 Answers 8

269

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. } 
Sign up to request clarification or add additional context in comments.

5 Comments

How can I do two arguments?
Or do I send an object full of more than one argument?
@soo: Use a helper class or a Tuple<A,B> (C#4+) (Edit: Yes, use an object to pack it all in. See for example DoWorkEventArgs self).
But how do you notify the UI of the result?
@rayray: label1.Text = e.Result.ToString(); , everywhere I marked that as safe.
109

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

5 Comments

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 quantnet.com/threads/c-c-vba-or-java.11433
How about 3 parameters?
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) {...
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.
But how does the value get passed into RunWorkerAsync?
57

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

3 Comments

@missReclusive cast the "genericlist" items,i.e,Let say "argument 1" is of type int then int argument1=(int)genericlist[0]
this is a bad idea in terms of maintenance. You should use concrete types over List<object> because at least you'll be able to figure out what you were doing (see an example in my answer below)
I'd probably prefer a Tuple (or a specialised class) rather than a list of generic objects
9

You can use the DoWorkEventArgs.Argument property.

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

Comments

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

Comments

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

2 Comments

+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 stackoverflow.com/a/12231431/503621 & stackoverflow.com/questions/12507602/…
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!
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 } 

Comments

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.