I made a simple application that calls a slow performing task using background workers. I would like to be able to pass some arguments to the slow function and get results when the task is complete. I am able to do this by using global variables a, b and product. Is there a better way to pass arguments to the slow function and get back the result?
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.ComponentModel; // for BackgroundWorker
namespace ThreadsDelegate
{
/// <summary>
/// Description of MainForm.
/// </summary>
public partial class MainForm : Form
{
Random rnd = new Random();
int a; // will be used by the slow task
int b; // will be used by the slow task
string product = null; // we get back the result of the slow task
int i = 0; // counter
public MainForm()
{
InitializeComponent();
listBox1.Items.Add("Starting a long task of multiplication, that takes a few seconds.");
listBox1.Items.Add("We can still use the form interface for other activities, such as generating random numbers...");
listBox1.Items.Add("We can call the multiplication function multiple times by pressing the button and it will return multiple answers");
listBox1.Items.Add("When the multiplication task is complete, the results will be displayed");
}
void BtnRandomClick(object sender, EventArgs e)
{
int number = rnd.Next(0, 1000);
tbRandomNumber.Text = number.ToString();
}
void BtnSlowTaskClick(object sender, EventArgs e)
{
a = rnd.Next(1, 9); // we use global variables to pass data to slow function
b = rnd.Next(11, 22); // we use global variables to pass data to slow function
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += new DoWorkEventHandler(SlowMultiply);
bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
bg.RunWorkerAsync();
}
void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
listBox1.Items.Add((++i) + ". Result of multiplication: " + product);
}
void SlowMultiply(object sender, DoWorkEventArgs e)
{
int prod = a * b;
for (int i = 1; i <= 5; i++)
{
Thread.Sleep(500);
}
product = prod.ToString(); // update the global variable
}
}
}
You can send parameters through a background worker like this:
int a = rnd.Next(1, 9);
int b = rnd.Next(11, 22);
var data = new Tuple<int, int>(a, b);
bg.RunWorkerAsync(argument: data);
And then in your worker method
void SlowMultiply(object sender, DoWorkEventArgs e)
{
var mydata = (Tuple<int, int>) e.Argument;
int product = mydata.Item1 * mydata.Item2;
for (int i = 1; i <= 5; i++)
{
Thread.Sleep(500);
}
product = prod.ToString(); // update the global variable
}
}
And alternatively, you could just calculate the random numbers inside of your worker method.