如何避免事件订阅的重复

本文关键字:何避免 事件 | 更新日期: 2023-09-27 18:04:09

我有3个类,即登录,条形码和主要。
登录类只包含用户的身份验证。
Barcode类具有以下代码片段:

    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);
      }
    }

在Main类中,完成了Barcode事件的订阅:

    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
      }
    }

当我尝试登出并再次登录时发生事件订阅重复。
当我尝试调试时,BarcodeReadOut被调用了两次。
在注销时,调用removeInstance(),在打开登录屏幕之前,Main表单是Close()和Dispose()。
有人可以帮助我如何才能避免重复说的事件?

我在注册事件之前也这样做了,但是什么也没有发生:

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

如何避免事件订阅的重复

您应该按如下方式添加和删除处理程序:

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
  }
}

另外:您不需要定义自定义委托,您可以使用通用的EventHandler:

public event EventHandler<BarcodeEventArgs> BarcodeReadOut;

最好将所有与Barcode一起工作的逻辑移到单独的类中。添加一个自定义事件,通知其他类(在您的情况下是Form类)事件已经发生,这可能会很好:

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);
    }
}

并像这样使用:

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