3

I am experimenting with BackgroundWorker, and trying to notify my main Thread per an Event. These things are all new to me, and wanted to ask, if I am doing it OK.

I simplified a winforms problem of mine, in the following way: (It has only 1 Button, and counts to ten in another Thread when I press it)

public partial class Form1 : Form
{
    public void Subscribe(CountToTen c)
    {
        c.HandleWorkerEvent += new CountToTen.WorkerHandler(OtherThreadFinished);
    }
    private void OtherThreadFinished(CountToTen c, EventArgs e)
    {
        Debug.WriteLine("I'm ready !!!");
    }

    public Form1()
    {
        InitializeComponent();
    }

    private void btn_do_Click(object sender, EventArgs e)
    {
        CountToTen newThread = new CountToTen();
        Subscribe(newThread);
        newThread.StartCountingAndReportIfFinished();
    }
}

CountToTen class:

public class CountToTen
{

    public event WorkerHandler HandleWorkerEvent;
    public EventArgs e;
    public delegate void WorkerHandler(CountToTen c, EventArgs e);
    public void StartCountingAndReportIfFinished()
    {
        BackgroundWorker worker = new BackgroundWorker();

        worker.DoWork += delegate(object s, DoWorkEventArgs args)
        {
            for (int i = 1; i <= 10; i++)
            {
                Thread.Sleep(300);
                Debug.WriteLine("Counting :" + i.ToString());

            }
        };

        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(delegate(object o, RunWorkerCompletedEventArgs args)
            {
                Debug.WriteLine("Fromt Thread2 : I am finished!");
                if (HandleWorkerEvent != null)
                {
                    HandleWorkerEvent(this, e);
                }
            });

        worker.RunWorkerAsync();
        worker.Dispose();
    }
}

I was trying to create an event, when the BW is finished, and subscribe to this event in my main form. It works fine, but, I do not really understand what happens in this line:

worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(delegate(object o, RunWorkerCompletedEventArgs args)
            {
                Debug.WriteLine("Fromt Thread2 : I am finished!");
                if (HandleWorkerEvent != null)
                {
                    HandleWorkerEvent(this, e);
                }
            });

Am I not creating an event here for my BW, when it is finished, and then call the another for the main thread? Is it not overkill? Could I subscribe directly to the RunWorkerCompleteEventHandler as well?

I'm a bit confused here, please enlighten a beginner. Thanks

Onsightfree
  • 307
  • 3
  • 11

3 Answers3

2

This is a subscription to RunWorkerCompleted event of BackgroundWorker. You can do this either with anonymous method, or with named method. Also you can remove delegate type declaration this way:

worker.RunWorkerCompleted += (o, args) => 
{
    // raise HandleWorkerEvent if there is any subscriber exists
    if (HandleWorkerEvent != null)    
        HandleWorkerEvent(this, e);

    worker.Dispose();
};

With named method this will look like

worker.RunWorkerCompleted += Worker_RunWorkerCompleted;

Handler:

void Worker_RunWorkerCompleted(object o, RunWorkerCompletedEventArgs args)
{
    if (HandleWorkerEvent != null)    
        HandleWorkerEvent(this, e);

    ((BackgroundWorker)o).Dispose();
}

BTW I think it's better to have class, which will only have counting to ten logic. Create BackgroundWorker on your form, and use this class in DoWork event handler. Also form will dispose all its components.

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • So just to be sure, you are saying that with this line I am subscripting to the BW Completed Event? ( worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(delegate(object o, RunWorkerCompletedEventArgs args) ) These delegates confuse the hell outta me I guess - also VS has some syntax problems with your first snippet, but thanks so far ! – Onsightfree Jan 18 '13 at 12:21
  • @Onsightfree [Lambda expressions](http://msdn.microsoft.com/en-us/library/bb397687.aspx) are available since VS 2008. Which VS do you have? – Sergey Berezovskiy Jan 18 '13 at 12:26
  • I've 2012express, but I have figured it out, it has to be }; and not });. Was just a bracket too much, thats all :) – Onsightfree Jan 18 '13 at 12:31
  • @Onsightfree sorry, that bracket left from your original delegate creation :) removed now. And again, consider to use BW on your Form. When you place it to form, BW registered as components, thus BW will be disposed automatically when form closes. – Sergey Berezovskiy Jan 18 '13 at 12:40
  • Thanks, I will give it a try, but it raises a lot of questions in me again, because as the next step I want to report progress, and I already know how to in this architecture (will use this for FTP later). If I cannot figure it out, will post another question about that :) – Onsightfree Jan 18 '13 at 12:49
0

You can subscribe to RunWorkerCompleted event of your BackgroundWorker directly, but it depends on your business logic and architecture.

chameleon
  • 984
  • 10
  • 15
0
Am I not creating an event here for my BW, when it is finished,
 and then call the another for the main thread?

Yes.. You are handling the events of BackgroundWorker in your CountToTen class. And Obviously as per your class architecture the only way to notify your mainform through Event.

  Is it not overkill? Could I subscribe directly to the RunWorkerCompleteEventHandler
  as well? 

Ofcourse you can..Your BackgroundWorker is not exposed directly to the mainform else you can subscribe the RunWorkerCompletedEvent from there itself.

Note: You don't have to call Dispose(). It implements the IDisposable interface via Component. For detail see here

Update

  • Alternative way

    public partial class Form1 : Form
    {
      private void btn_do_Click(object sender, EventArgs e)
      { 
        CountToTen obj= new CountToTen();
         obj.bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
         obj.bw.RunWorkerAsync();
       }
    
       void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){}       
    }
    class CountToTen 
    {
    public BackgroundWorker bw = new BackgroundWorker();
    public CountToTen()
    {
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
    }
    
    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        //Do your Stuff
    }
    }
    
Community
  • 1
  • 1
C-va
  • 2,910
  • 4
  • 27
  • 42
  • I just realized my question was also not clear enough, thats why I am not sure I understand the second part of your answer. Are you saying that in the code I posted above, I cannot subscribe for the BW event, from my main form, as it is created in a method of another class? – Onsightfree Jan 18 '13 at 12:44
  • Exactly..Have you tried access the Background worker's event from main form by creating the background worker outside of the method and expose it to mainform – C-va Jan 18 '13 at 12:59
  • Thanks, I accepted your approach as an answer, as it was clearer to me as lazyberezovsky 's. Pity I cant accept both. Cheers – Onsightfree Jan 18 '13 at 13:34