6

これはスレッドセーフですか?

PrismのEventAggregatorは、メソッドが1つしかない非常に単純なクラスです。nullチェックの周りにロックがなく、private_eventsコレクションに追加する新しいタイプが作成されていることに気付いたときは驚きました。2つのスレッドが同じタイプに対して同時にGetEventを呼び出した場合(_eventsに存在する前)、これによりコレクションに2つのエントリが作成されるように見えます。

    /// <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. スレッドセーフのMSDNによると、Listクラス自体のインスタンスメンバーアクセスはスレッドセーフではありません。
  2. メソッド自体はスレッドセーフではありませ ん
    1. 2つのスレッドが同時にメソッドに入る可能性があります
    2. どちらもFirstOrDefaultを取得しようとします
    3. どちらも何も得られない
    4. どちらも新しいTEventTypeを追加します

私は...するだろう

  1. .NET4のSystem.CollectionConcurrentXコレクションの1つに切り替えます
    http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx
    または
  2. 独自のロックを行う
于 2010-05-15T00:58:36.370 に答える
0

「_events」が何であるかによります...

.NET4にはいくつかの素晴らしい新しいスレッドセーフクラスがあります... http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx
をチェックしてください

于 2010-05-14T12:46:00.250 に答える
0

ええと、そのコードペーストに基づいて、私はノーと言います、それは100%スレッドセーフではありません。

もちろん、ソースがあるので、自分でロックを追加するだけです。:)

実際、一般的な経験則として、少なくとも最初は、CALプロジェクト全体をソリューションに含めています。それはそれらの奇妙な領域の登録/作成の例外をデバッグするのに大いに役立ちます...

于 2010-05-14T20:59:48.470 に答える