2009-05-28 12 views
7

私は.NETライブラリで利用できる特別なデータ構造を書いています。このデータ構造の特徴の1つは、スレッドセーフであるということです。ただし、1つのスレッドのみがデータを書き込み、それからのデータ(リーダスレッドとライタスレッドは異なる可能性があります)。.NETでクロススレッドアクセスを検出する方法(スレッドアフィニティを実施する)?

問題は、すべての読み取り操作が同じスレッドで実行されるように強制することができますか?

私の解決策は、System.Threading.Thread.ManagedThreadIDをキャプチャして、最初の読み取り時にプライベートメンバーに格納します。次に、後続の読み取りでManagedThreadIDを保存されたものと比較し、異なる場合は例外をスローします。

これで十分ですか、これを行うには信頼性の高いメカニズムがあります。

注:このライブラリはのWindows.Formsコンテキストなしで使用可能であるという要件があります。..

答えて

6

私はこの状況に遭遇すると、私はThreadAffinityという名前のクラスを使用します。現在のスレッドを記録し、別のスレッドから無効なアクセスを投げるのが目的です。手動でチェックを行う必要がありますが、少量の作業をカプセル化します。

class Foo { 
    ThreadAffinity affinity = new ThreadAffinity(); 

    public string SomeProperty { 
    get { affinity.Check(); return "Somevalue"; } 
    } 
} 

クラス

[Immutable] 
public sealed class ThreadAffinity 
{ 
    private readonly int m_threadId; 

    public ThreadAffinity() 
    { 
     m_threadId = Thread.CurrentThread.ManagedThreadId; 
    } 

    public void Check() 
    { 
     if (Thread.CurrentThread.ManagedThreadId != m_threadId) 
     { 
      var msg = String.Format(
       "Call to class with affinity to thread {0} detected from thread {1}.", 
       m_threadId, 
       Thread.CurrentThread.ManagedThreadId); 
      throw new InvalidOperationException(msg); 
     } 
    } 
} 

テーマに関するブログ記事:

+0

Thanks Jared。ちょうど興味があります、あなたは@ sixlettervariablesの答えが良い/悪くなる理由を見ますか? –

+1

@Miky D、私はそれが責任を混同しているので、それが悪いと言っている唯一の理由です。無効なクロススレッドアクセスをチェックするための別のクラスを持つことは、一貫した再利用可能なエクスペリエンスを提供します。それは非常に少量のコードだけど、あなたが実際にはめ込むことができる唯一のものはエラーメッセージなので、IMHOはそれほど大したことではありません。 – JaredPar

+0

JaredParはクラスを使用している限り、私はManaged IDを使用していないことに同意します。しかし、はい、+1ロジックを扱う別のクラスを使用します。 – user7116

1

はあなたが読んを必要とするメソッドを書くことができませんでしたが、スレッドまたはスレッドIDを取りますか?次に、最初に呼び出したものと比較するだけで、一致しない場合は例外をスローするか、エラーコードを返すか、要求を無視します。

そうでなければ、あなたが提案するものもまた動作するはずです。スレッドIDを比較するだけで済みます。

+0

私は、読み取り/書き込みメソッドの呼び出し元何に頼るのは嫌です入力として提供されています..それ以外の場合は、私は確実にManagedThreadIDメソッドを使用することができます私はそれを使用すると思います。ありがとう。 –

1

スレッドIDを比較するのではなく、建設中にクラスにambient Threadを保存する必要があります。

class SingleThreadedClass 
{ 
    private Thread ownerThread; 

    public SingleThreadedClass() 
    { 
     this.ownerThread = Thread.CurrentThread; 
    } 

    public void Read(...) 
    { 
     if (Thread.CurrentThread != this.ownerThread) 
      throw new InvalidOperationException(); 
    } 

    public void TakeOwnership() 
    { 
     this.ownerThread = Thread.CurrentThread; 
    } 
} 
+0

スレッドIDとは対照的に、スレッドへの参照を使用する必要がある具体的な理由はありますか?あなたの技術は、IDの代わりにスレッドへの参照を使用する点を除いて、私の技術と非常によく似ています。ちょっと興味があります.. –

+0

管理されたスレッドIDがリサイクルされるのは心配です。また、スレッドで管理IDよりも多くのことを行うことができます。 – user7116

関連する問題