6

这是线程安全的吗?

Prism 中的 EventAggregator 是一个非常简单的类,只有一个方法。当我注意到空检查和创建新类型以添加​​到私有 _events 集合时没有锁定时,我感到很惊讶。如果两个线程同时为同一类型调用 GetEvent(在它存在于 _events 之前),看起来这将导致集合中的两个条目。

    /// <summary>
    /// Gets the single instance of the event managed by this EventAggregator. Multiple calls to this method with the same <typeparamref name="TEventType"/> returns the same event instance.
    /// </summary>
    /// <typeparam name="TEventType">The type of event to get. This must inherit from <see cref="EventBase"/>.</typeparam>
    /// <returns>A singleton instance of an event object of type <typeparamref name="TEventType"/>.</returns>
    public TEventType GetEvent<TEventType>() where TEventType : EventBase
    {
        TEventType eventInstance = _events.FirstOrDefault(evt => evt.GetType() == typeof(TEventType)) as TEventType;
        if (eventInstance == null)
        {
            eventInstance = Activator.CreateInstance<TEventType>();
            _events.Add(eventInstance);
        }
        return eventInstance;
    }
4

3 回答 3

4

不,不是线程安全的。

  1. List 类本身的实例成员访问不是线程安全的,根据MSDN 下的线程安全
  2. 方法本身不是线程安全 的
    1. 2个线程可以同时进入方法
    2. 两者都尝试获取 FirstOrDefault
    3. 两者都一无所获
    4. 两者都添加了一个新的 TEventType

我会

  1. 切换到 .NET 4
    http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx
    中的 System.CollectionConcurrentX 集合之一 或
  2. 做你自己的锁定
于 2010-05-15T00:58:36.370 回答
0

好吧,基于该代码粘贴,我会说不,它不是 100% 线程安全的。

当然,你有源,所以你可以自己加锁。:)

实际上,作为一般经验法则,我将整个 CAL 项目包含在我的解决方案中,至少在开始时是这样。它对调试那些奇怪的区域注册/创建异常有很大帮助......

于 2010-05-14T20:59:48.470 回答
0

这取决于“_events”是什么......

.NET 4 中有一些很棒的新线程安全类...
查看http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx

于 2010-05-14T12:46:00.250 回答