Search code examples
c#winformsbackgroundworker

c# Background worker does not exit


I'm using a background worker to listen to UDP and then doing the processing. I want to exit when I click on button2

  public snmpmain()
    {
        InitializeComponent();
        backsnmp = new BackgroundWorker();
        backsnmp.DoWork += new DoWorkEventHandler(backsnmp_DoWork);
        backsnmp.ProgressChanged += new ProgressChangedEventHandler
               (backsnmp_ProgressChanged);
        backsnmp.WorkerReportsProgress = true;
        _startsnmp = true;
        backsnmp.WorkerSupportsCancellation = true;


    }

private void button1_Click(object sender, EventArgs e)
    {
        button1.Enabled = false;
        this.backsnmp.RunWorkerAsync();
      }

    private void button2_Click(object sender, EventArgs e)   
       /* it executes this when button2 is pressed but nothing happens. I can receive the UDP packets the dowork hasn't stopped*/
    {
        _startsnmp = false;
        backsnmp.CancelAsync();
        listBox1.Items.Add("SNMP Stopped");

        }

 void backsnmp_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        listBox1.Items.Add (e.UserState as String);        
     }

  void backsnmp_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Cancelled)
        {
            listBox1.Items.Add("SNMP Stopped");
            button2.Enabled = false;
            button1.Enabled = true;
        }
    }

  void backsnmp_DoWork(object sender, DoWorkEventArgs e)
    {

        backsnmp.ReportProgress(0, "Initializing SNMP Listener on Port:" + port + "...");
             UdpClient listener = new UdpClient(port);
            IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, port);

            while (true)
            {

                if (backsnmp.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }


                   Thread.Sleep(100);


                    backsnmp.ReportProgress(0, "Waiting for messages....");

       packet = listener.Receive(ref groupEP);   // When I press button2 it's right here


                  // do some work here

It goes and executes button2_Click when I click on button2, but nothing really happens. The dowork isn't cancelled. I can still receive the packets.


Solution

  • listener.Receive blocks until data is received. Hence your cancellation isn't recognized at all.

    What you could do is either using BeginReceive (and get rid of the BackgroundWorker) or try to make listener a class field and dispose it when cancelling. The latter should leave the blocking receive with an exception though. Well - or send a message to the listener yourself after cancelling (which obviously will wake the receiver as well).