如何确保事件只能订阅一次 [英] How to ensure an event is only subscribed to once

查看:98
本文介绍了如何确保事件只能订阅一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想确保我只在一个特定的类中订阅了一个实例上的事件。

I would like to ensure that I only subscribe once in a particular class for an event on an instance.

例如,我想要能够以下:

For example I would like to be able to do the following:

if (*not already subscribed*)
{
    member.Event += new MemeberClass.Delegate(handler);
}

我将如何执行这样的守卫?

How would I go about implementing such a guard?

推荐答案

如果您正在谈论一个类上的事件,那么您可以访问源代码,那么您可以将该警卫置于事件定义中。 p>

If you are talking about an event on a class that you have access to the source for then you could place the guard in the event definition.

private bool _eventHasSubscribers = false;
private EventHandler<MyDelegateType> _myEvent;

public event EventHandler<MyDelegateType> MyEvent
{
   add 
   {
      if (_myEvent == null)
      {
         _myEvent += value;
      }
   }
   remove
   {
      _myEvent -= value;
   }
}

这将确保只有一个订阅者可以订阅事件发生在提供事件的类的这个实例上。

That would ensure that only one subscriber can subscribe to the event on this instance of the class that provides the event.

编辑请查看有关为什么上述代码是坏主意而不是线程的注释

EDIT please see comments about why the above code is a bad idea and not thread safe.

如果您的问题是客户端的单个实例不止一次订阅(您需要多个订阅者),则客户端代码将需要处理那。所以更换

If your problem is that a single instance of the client is subscribing more than once (and you need multiple subscribers) then the client code is going to need to handle that. So replace


尚未订阅

与您首次订阅该事件时设置的客户端类的bool成员。

with a bool member of the client class that gets set when you subscribe for the event the first time.

编辑(接受后):根据@Glen T(问题的提交者)的评论,他接受的解决方案的代码是在客户端类中:

Edit (after accepted): Based on the comment from @Glen T (the submitter of the question) the code for the accepted solution he went with is in the client class:

if (alreadySubscribedFlag)
{
    member.Event += new MemeberClass.Delegate(handler);
}

where alreadySubscribedFlag是客户端类中跟踪第一个订阅的成员变量具体事件。
在这里查看第一个代码片段的人,请注意@ Rune的评论 - 以非常明显的方式更改订阅事件的行为不是一个好主意。

Where alreadySubscribedFlag is a member variable in the client class that tracks first subscription to the specific event. People looking at the first code snippet here, please take note of @Rune's comment - it is not a good idea to change the behavior of subscribing to an event in a non-obvious way.

EDIT 31/7/2009:请参阅@Sam Saffron的评论。正如我已经说过的,Sam同意这里提出的第一种方法并不是修改事件订阅行为的合理方法。类的消费者需要了解其内部实现来了解其行为。不是很好。

@Sam Saffron还评论了线程安全性。我假设他是指可能的竞争条件,其中两个订阅者(接近)同时尝试订阅,并且可能都会结束订阅。可以使用锁来改善这一点。如果您打算改变事件订阅的工作方式,那么我建议您了解如何使订阅添加/删除属性线程安全

EDIT 31/7/2009: Please see comments from @Sam Saffron. As I already stated and Sam agrees the first method presented here is not a sensible way to modify the behavior of the event subscription. The consumers of the class need to know about its internal implementation to understand its behavior. Not very nice.
@Sam Saffron also comments about thread safety. I'm assuming that he is referring to the possible race condition where two subscribers (close to) simultaneously attempt to subscribe and they may both end up subscribing. A lock could be used to improve this. If you are planning to change the way event subscription works then I advise that you read about how to make the subscription add/remove properties thread safe.

这篇关于如何确保事件只能订阅一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆