Dariusz Tarczynski
Dariusz Tarczynski

Reputation: 16721

Run method with BackgroundWorker on second Form

Let's imagine that we have two Forms: MainForm and WaitingForm. I want to pass, from MainForm, to the WaitingForm the method to run in background using BackgroundWorker.

Now, I'm doing things that way:

MainForm.cs:

public partial class MainForm: Form
{
    private void btnImport_Click(object sender, EventArgs e)
    {
        var waitingFrm = new WaitingForm();
        waitingFrm.DoWork = (o, args) => this.LongRunningOperation(this, new DoWorkEventArgs("foo bar"));
        waitingFrm.OnWorkCompleted = (o, args) => MessageBox.Show("Finished!");
        waitingFrm.Show();
        waitingFrm.Run(); // should execute LongRunningOperation, method below.
    }

    private void LongRunningOperation(object sender, DoWorkEventArgs e)
    {
        MessageBox.Show("Running long operation!....");
        // some long running stuff here;
    }
}

WaitingForm.cs

public partial class WaitingForm: Form
{
    private BackgroundWorker worker = new BackgroundWorker();
    public DoWorkEventHandler DoWork { get; set; }
    public RunWorkerCompletedEventHandler OnWorkCompleted { get; set; }

    public WaitingForm()
    {
        this.worker.DoWork += DoWork;
        this.worker.RunWorkerCompleted += OnWorkCompleted;
        InitializeComponent();
    }

    public void Run()
    {
        this.worker.RunWorkerAsync();
    }
}

But after waitingFrm.Run(); my LongRunningOperation is not executed.

Upvotes: 0

Views: 1699

Answers (4)

Chibueze Opata
Chibueze Opata

Reputation: 10054

So, the simple answer is that. Your code is not working because the mainform is not seeing the BackgroundWorker object instance events. Instead of doing:

    this.worker.DoWork += DoWork;
    this.worker.RunWorkerCompleted += OnWorkCompleted;

in WaitingForm - InitializeComponent(), do this instead in mainForm like this:

    waitingFrm.worker.DoWork += waitingFrm.DoWork;
    waitingFrm.worker.RunWorkerCompleted += waitingFrm.OnWorkCompleted;

Upvotes: 1

JaredPar
JaredPar

Reputation: 754745

In this particular case you want all of the work to happen in MainForm and it looks like WaitingForm is just a display for the user. If that's the case then I would just put the BackgroundWorker in the MainForm and use the event to call into WaitingForm

public partial class MainForm: Form
{
  private void btnImport_Click(object sender, EventArgs e) {
    var waitingForm = new WaitingForm();
    waitingForm.Show();
    var worker = new BackgroundWorker();
    worker.DoWork += (o, args) => this.LogRunningOperation(o, args);
    worker.OnWorkComplete += (o, args) => {
      waitingForm.Close();
      worker.Dispose();
    };
    worker.RunWorkerAsync();
  }

  private void LongRunningOperation(object sender, DoWorkEventArgs e) {
    MessageBox.Show("Running long operation!....");
    // some long running stuff here;
  }
}

Upvotes: 1

Ricibob
Ricibob

Reputation: 7705

In your WaitingForm I'd do:

public event DoWorkEventHandler DoWork {
    add { worker.DoWork += value; } 
    remove { worker.DoWork += value; }
}

(Instead of the get;set; property). And then in your main window btnImport_Click handler just:

waitingFrm.DoWork += LongRunnignOperation;

And the same for completed handler. Your syntax seems overly complicated. This is just a clean way to expose an event (in this case on your waitingform) and the pass event handler through to the real handler (in this case worker.DoWork). It is equivalent to

 waitingFrm.worker.DoWork += LongRunnignOperation;

which would do just as well.

Upvotes: 1

Tigran
Tigran

Reputation: 62246

I want to pass, from MainForm, to the WaitingForm the method to run in background using BackgroundWorker

I would in this case

  • declare an event in WaitingForm
  • before Form1 shows WaitingForm subscribes to that event
  • when long running operation has to be runned WaitingForm raise an event, Form1 gets it and Form1 runs its method in other thread.

Hope this helps.

Upvotes: 1

Related Questions