代码之家  ›  专栏  ›  技术社区  ›  xtofl Adam Rosenfield

多线程观察器的设计模式

  •  1
  • xtofl Adam Rosenfield  · 技术社区  · 16 年前

    在数字信号采集系统中,数据通常由一个线程推送到系统中的观测器中。

    例子来自 Wikipedia/Observer_pattern :

    foreach (IObserver observer in observers)
        observer.Update(message);
    

    例如,当来自GUI线程的用户操作要求数据停止流动时,您希望断开主题观察者连接,甚至一起处理观察者。

    有人可能会说:您应该停止数据源,然后等待sentinel值来处理连接。但这会在系统中引起更多的延迟。

    当然,如果数据抽取线程刚刚请求观察者的地址,它可能会发现它正在向一个被破坏的对象发送一条消息。

    有人创造了一种“官方”设计模式来应对这种情况吗?他们不应该吗?

    2 回复  |  直到 16 年前
        1
  •  2
  •   QBziZ    16 年前

    如果您希望让数据源始终处于并发的安全方面,那么您应该至少有一个指针,该指针对于他使用总是安全的。 所以观察者对象应该有一个不早于数据源的生命周期。

    这只能通过添加观察者来完成,但不能删除它们。 您可以让每个观察者不执行核心实现本身,而是让它将此任务委托给一个observerimpl对象。 您锁定了对此IMPL对象的访问。这没什么大不了的,它只是意味着如果观察者忙于使用observerimpl对象,那么GUI取消订阅者将被阻塞一段时间。如果GUI响应是一个问题,那么您可以使用某种并发作业队列机制,将一个取消订阅作业推送到它上面。(类似于Windows中的邮件)

    取消订阅时,只需将核心实现替换为虚拟实现。同样,此操作应抓住锁。这确实会引入一些等待数据源的过程,但是由于它只是一个[锁定指针交换-解锁]过程,所以您可以说这对于实时应用程序来说已经足够快了。

    如果您想避免将只包含虚拟对象的观察者对象堆叠在一起,则必须进行某种类型的簿记,但这可以归结为一些琐碎的事情,例如对象持有指向列表中所需的观察者对象的指针。

    优化: 如果您还让实现(真实的+虚拟的)在观察者本身的时间内保持活动,那么您可以在没有实际锁的情况下执行此操作,并使用类似interlockedexchangepointer的东西来交换指针。 最坏的情况:在交换指针时正在进行委派调用-->没什么大不了的,所有对象都保持活动状态,委派可以继续。下一个委托调用将是新的实现对象。(当然,除非有任何新的掉期交易)

        2
  •  0
  •   Tim Cooper    12 年前

    您可以向所有观察者发送一条消息,通知他们数据源正在终止,并让观察者从列表中删除自己。

    作为对评论的回应,主题观察者模式的实现应允许动态添加/删除观察者。在C中,事件系统是一个主题/观察者模式,其中使用 event += observer 并用 event -= observer .

    推荐文章
    El.Hum  ·  SSIS不识别索引?
    7 年前