【问题标题】:Is it possible to restrict set/reset of EventWaitHandle?是否可以限制 EventWaitHandle 的设置/重置?
【发布时间】:2014-10-23 21:46:07
【问题描述】:

我想要一个 EventWaitHandle 对象(例如 ManualResetEvent),它只能从一个地方设置/重置,但可以从多个地方等待(使用 WaitOne())。换句话说,我希望只有一个类可以设置/重置它,而所有其他类都可以调用 WaitOne() 。这有点像常规的“只读”属性:

private string MyReadOnlyText {get; private set;}

仅适用于 ManualResetEvent 中的特定方法。但不是:

private ManualResetEvent MyEvent {get; private set;}

当然,这是行不通的,因为只有所有者类可以实例化此属性,而任何其他外部对象都可以使用 MyEvent.Set/MyEvent.Reset() 来更改它。

这样的事情可能吗?这样做的目的是防止应用程序中的任意对象操纵等待句柄状态,并确保这可以仅从一个地方完成。

【问题讨论】:

  • 你不能把你正在使用的任何等待原语包装在一个自定义类中,它具有你想要的属性(只有实例的创建者可以设置/重置),然后使用它贯穿始终?

标签: c# .net multithreading synchronization event-wait-handle


【解决方案1】:

在某种程度上,这似乎可以通过约定来解决,即只规定句柄应被消费者视为“只读”。对源代码进行简单的 grep 操作应该有助于防止不法分子。

如果您仅将对象公开为WaitHandle,则对“仅真实”事件概念的支持有限。 WaitHandle 实例没有 Set() 方法,因此有助于提醒调用者不要乱用它。

当然,调用者仍然可以将其转换为实际类型,WaitHandle 中的静态方法仍然允许操作。因此,这并不是 100% 的保证。但这会有所帮助(并在您进行代码审核时提供更多独特的模式供您使用 grep)。

最后,cmets 中提到的“包装器”方法也可以工作。这是最健壮的,对于任何类型的“限制对除所有者对象之外的成员的访问”都是一种相对常见的模式。

如果调用者与特权代码在不同的程序集中,那么最简单的方法是使隐藏的东西“内部”和公共的东西“公共”。如果它们在同一个程序集中,那么如果你可以将隐藏成员与特权代码放在同一个类中,那么它们当然可以是该类的私有。

通常,您希望将特殊可访问性对象封装为一个单独的类,同时仍授予对一个特定类的特权访问权限并限制其他所有人的访问权限。在这种情况下,您可以使用嵌套类来实现这种分离,外部类包含特权代码,而嵌套类包含隐藏代码。

这种方法的一个版本使用基类/子类设计,其中基类具有公共成员,子类具有隐藏代码:

class A
{
    public class B
    {
        protected ManualResetEvent _event = new ManualResetEvent(false);

        public void Wait() { _event.Wait(); }
    }

    private class C : B
    {
        public void Set() { _event.Set(); }
    }

    public B GetAnInstanceofB() { return new C(); }

    private void DoSomethingWithB(B b) { ((C)b).Set(); }
}

现在调用者可以在返回的实例上调用B.Wait(),但他们不能转换为C 类型来访问Set() 方法。但请注意,A 类中的代码是允许的(因为它可以将类型强制转换为 C)。

请注意,B 类本身不需要嵌套。只需C

这个主题的另一个变体是声明一个只包含公共方法的接口,然后有一个接口的实现者。同样,实现类将嵌套为特权代码私有,而接口可以嵌套或不嵌套。

最后请注意,所有这些都与代码可靠性和维护有关。当然,代码总是可以使用反射来检查和访问它想要的任何类型的任何部分。

归根结底,您必须考虑代码的受众。如果它是一个小团队,并且代码完全独立于一个项目,那么只告诉所有人“你可以等待这个,但不要搞砸这个事件”可能就足够了。在更大的环境中,可能有几个团队一起从事多个相关项目,但基本上仍然是一个独立的单元,使用WaitHandle 可能就足够了。如果您正在编写一个打算广泛使用的库,那么封装和私有成员和类是一个很好的工具。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2014-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多