简体   繁体   中英

How to avoid duplication of event subscription?

I have 3 classes namely Login, Barcode, and the Main.
Login class just contains the authentication of the users.
Barcode class has the following snippet code:

    class Barcode
    {
      public delegate void BarcodeReadHandler(object sender, BarcodeEventArgs e);
      public event BarcodeReadHandler BarcodeReadOut;

      public Barcode()
      {
        //.. some codes for getting data on the scanner
        BarcodeEventArgs args = new BarcodeEventArgs(scannedData);
        BarcodeReadOut(this, args);
      }

    }

While in Main class, the subsciption of the Barcode event is done:

    public partial class Main : Form
    {
      private Barcode barcode = null;

      public Main()
      {
        barcode.BarcodeReadOut += new barcode.BarcodeReadHandler(getBarcodeStr);
      }

      //This is called before log-out.
      public void removeInstance() 
      {
        barcode.BarcodeReadOut -= new barcode.BarcodeReadHandler(getBarcodeStr);
      }

      private void getBarcodeStr(object sender, BarcodeEventArgs e)
      {
        //some code
      }

    }

The duplication of event subscription happens when I try to logout and login again.
When I tried to debug, BarcodeReadOut is called twice.
In logout, the removeInstance() is called and the Main form is Close() and Dispose() before opening the login screen.
Can someone help me on how can I avoid the duplication of the said events?

I also have done this before registering the event but nothing happens:

    public Main()
    {
        barcode.BarcodeReadOut -= new barcode.BarcodeReadHandler(getBarcodeStr);
        barcode.BarcodeReadOut += new barcode.BarcodeReadHandler(getBarcodeStr);
    }

You should add and remove the handler as follows:

public partial class Main : Form
{
  private Barcode barcode = null;

  public Main()
  {
    barcode.BarcodeReadOut += getBarcodeStr;
  }

  //This is called before log-out.
  public void removeInstance() 
  {
    barcode.BarcodeReadOut -= getBarcodeStr;
  }

  private void getBarcodeStr(object sender, BarcodeEventArgs e)
  {
    //some code
  }

}

Also: You don't need to define a custom delegate, you can use the generic EventHandler :

public event EventHandler<BarcodeEventArgs> BarcodeReadOut;

It would be good to move all your logic that works with Barcode to a separate class. And it might be good to add a custom event that notifies other classes (a Form class in your case) that event has occurred :

class Barcode
{
  public delegate void BarcodeReadHandler(object sender, BarcodeEventArgs e);
  public event BarcodeReadHandler BarcodeReadOut;

  public Barcode()
  {
    //.. some codes for getting data on the scanner
    BarcodeEventArgs args = new BarcodeEventArgs(scannedData);
    BarcodeReadOut(this, args);
  }

}

class BarcodeWorker
{
    private Barcode barcode = null;
    private BarcodeReadHandler handler;
    public event BarcodeEventArgs scanComplete;

    BarcodeWorker(Barcode barcode) 
    {
       if(barcode == null) this.barcode = barcode;
    }

    public AddEventHandler()
    {
       if(handler != null) return;
       handler = new BarcodeReadHandler(getBarcodeStr);
       barcode.BarcodeReadOut += handler;
    }

    //This is called before log-out.
    public void RemoveEventHandler() 
    {
       barcode.BarcodeReadOut -= handler;
       handler = null;
    }

    private void getBarcodeStr(object sender, BarcodeEventArgs e)
    {
       scanComplete(sender, e);
    }
}

And use it like this:

BarcodeWorker barcode = new BarcodeWorker();

barcode.scanComplete += // your delegate with event handler or with anonymous method here;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM