【问题标题】:How to avoid duplication of event subscription?如何避免重复订阅事件?
【发布时间】:2023-03-23 16:09:02
【问题描述】:

我有 3 个类,即 Login、Barcode 和 Main。
登录类只包含用户的身份验证。
Barcode 类有如下 sn-p 码:

    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(),主窗体是 Close() 和 Dispose(),然后再打开登录屏幕。
有人可以帮助我如何避免上述事件的重复吗?

我在注册活动之前也这样做了,但没有任何反应:

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

【问题讨论】:

  • 您可以通过反射清除所有事件订阅。看这里stackoverflow.com/questions/91778/…
  • 你可以检查barcode.BarcodeReadOut == null
  • 上面的链接很好,但请务必仔细阅读,因为接受的答案似乎不是最好的。
  • 在您的最后一段代码中,您删除另一个 BarcodeReadHandler 而不是添加。 (新)var bcr = 新条码.BarcodeReadHandler(getBarcodeStr);条形码.BarcodeReadOut -= bcr;条形码.BarcodeReadOut += bcr;会是正确的。

标签: c# events duplication subscribe


【解决方案1】:

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

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;

【讨论】:

    【解决方案2】:

    最好将所有适用于 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;
    

    【讨论】:

      猜你喜欢
      • 2010-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-04
      相关资源
      最近更新 更多