16

In my .NET C# project I have used a "BackgroundWorker" to call a method in a different class. The following is the source-code of my main form

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        testClass t1 = new testClass();
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            t1.changevalue(1000);
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            label1.Text += Convert.ToString(e.ProgressPercentage);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
        }
    }

and have the following code in a separate class file named "testClass.cs" in my project. I want to report the progress to the BackgroundWorker from this class, so that I will be able to display the progress in the main from label1.

class testClass
    {
        private int val;
        public int changevalue(int i)
        {
            for (int j = 0; j < 1000; j++)
            {
                val += i + j;
                //from here i need to preport the backgroundworker progress
                //eg; backgroundworker1.reportProgress(j);
            }
            return val;
        }
    } 

but I am not allowed to access BackgroundWorker from the "testClass".

Can someone please tell how to overcome this problem?

p.s- I have found this solution, but I don't understand it.

Community
  • 1
  • 1
PIKP
  • 753
  • 2
  • 15
  • 24

3 Answers3

33

You could just pass it in as a variable

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    t1.changevalue(1000, sender as BackgroundWorker);
}


class testClass
{
    private int val;
    public int changevalue(int i, BackgroundWorker bw)
    {
        for (int j = 0; j < 1000; j++)
        {
            val += i + j;
            bw.ReportProgress(i);
            //from here i need to preport the backgroundworker progress
            //eg; backgroundworker1.reportProgress(j);
        }
        return val;
    }
} 

But I think the best option would be an event in the testClass that your Form can assign to.

public partial class Form1 : Form
{
    private BackgroundWorker backgroundWorker1;
    private testClass t1 = new testClass();

    public Form1()
    {
        InitializeComponent();

        // subscribe to your event
        t1.OnProgressUpdate += t1_OnProgressUpdate;
    }

    private void t1_OnProgressUpdate(int value)
    {
        // Its another thread so invoke back to UI thread
        base.Invoke((Action)delegate
        {
            label1.Text += Convert.ToString(value);
        });
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        t1.changevalue(1000);
    }

    private void button1_Click_1(object sender, EventArgs e)
    {
        backgroundWorker1.RunWorkerAsync();
    }

}

class testClass
{
    public delegate void ProgressUpdate(int value);
    public event ProgressUpdate OnProgressUpdate;

    private int val;
    public int changevalue(int i)
    {
        for (int j = 0; j < 1000; j++)
        {
            val += i + j;

            // Fire the event
            if (OnProgressUpdate != null)
            {
                OnProgressUpdate(i);
            }
        }
        return val;
    }
} 
sa_ddam213
  • 42,848
  • 7
  • 101
  • 110
  • Than you so much Mr. @sa_ddam213. This is what exactly I was looking for. Your code works like charm. Cheers!! – PIKP Feb 14 '13 at 10:15
  • Your second solution looks a little bit more difficult to read. Why do you think it's better than the first? – Nolonar Aug 25 '14 at 09:18
  • 3
    @Nolonar , Well, the second version separates the `BackgroundWorker` from the logic class, not only that the class can now return progress regardless of it being used with a `BacgroundWorker` or not, you just need to subscribe to the 'OnProgressUpdate' event and that's it. – sa_ddam213 Aug 26 '14 at 07:12
1

I've just had this same issue (my long running process is a database restore), and solved it in a similar way by raising an event in the other class, but then had my subscriber to that event just act as a wrapper to backgroundWorker1.ReportProgress().

private void DBRestoreProgressHandler(DataAccess da, DataAccess.DatabaseRestoreEventArgs e)
    {
        backgroundWorker1.ReportProgress(e.RestoreProgress);
    }

private void backgroundWorker1_ReportProgress(object sender, ProgressChangedEventArgs e)
    {
        someLabel.Text = e.ProgressPercentage.ToString();
    }

This saved having to use:

base.Invoke((Action)delegate

Which I think can then cause problems if the form closes unexpectedly?

George Dando
  • 444
  • 2
  • 11
-2

Am i missing this in the above code ?:

backgroundWorker1 = new BackgroundWorker();

backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);

Knarf
  • 51
  • 4