2009-03-19 13 views
3

私は、プロパティが変更されたときにロックされるプライベートオブジェクトを使用して自身を同期させるオブジェクトを使用したい。 これを達成するための一般的な方法はありますか? 私のコードは、(1つのロッカーオブジェクトに)各プロパティに対して常にこのようになりますC#同期オブジェクト - 書き込みアクセサでコードを複製

private Object locker = new Object(); 
private int x; 
    public int X 
    { 
    get {return x;} 
    set{ 
     lock(locker){x=value;} 
    } 

あなたは、プロパティのスレッドセーフな修正を達成する簡単な方法です。

答えて

2

C#が新しいC#3.0機能でできることに驚いています。私はそこに何かを投げようとしていましたが、それはそうだと思っていましたが、私が望んでいたよりも良いことが判明しました。ここに 'tis。

すべての値を保持するオブジェクトを作成します(単に値の所有者としましょう...ただし、その用語の他の使用法と混同しないでください)。 C#の自動プロパティだけがあります。その後、価値所有者にアクセスできる別のオブジェクトを作成します。 2番目のオブジェクトを "SynchronicityHandler"と呼んでください。

SynchronicityHandlerにロックをさせてください。これは一般的なものになります。だからここにあなたが得るものです:私はそれについて考える、「値ホルダー」とは持っていない今、本当に

var myPerson = new SynchronicityHandler(new PersonValueHolder()); 

// Safely setting values 
myPerson.WorkWithValueHolderSafely(p => 
    { 
      p.FirstName = "Douglas"; 
      p.LastName = "Adams"; 
      p.HasCollegeDegree = true; 
    }); 

// Safely getting values (this syntax could be improved with a little effort) 
string theFirstName = null; 

myPerson.WorkWithValueHolderSafely(p=> theFirstName = p.FirstName); 

Console.Writeline("Name is: " + theFirstName); // Outputs "Name is: Douglass". 

:ここ

public class PersonValueHolder 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public bool HasCollegeDegree { get; set; } 
} 

public class SyncronicityHandler<T> 
{ 
    private object locker = new object(); 

    private T valueHolder; 

    public SynchronicityHandler(T theValueHolder) 
    { 
      this.valueHolder = theValueHolder; 
    } 

    public void WorkWithValueHolderSafely(Action<T> yourAction) 
    { 
      lock(locker) 
      { 
       yourAction(valueHolder); 
      } 
    } 
} 

は、あなたがそれを呼び出すと思います方法の例です自動的な特性に過ぎない。どのオブジェクトでもかまいません。

+0

邪悪なアイデア - ありがとう! – weismat

+0

あなたは賭けます。私はそれがあなたのために働く方法を聞くのが大好きです。 –

+0

これは 'string'のようなオブジェクトでうまくいくのでしょうか? – sarat

8

コードはそのように見えません。をロックする必要があります。を取得してください。それ以外の場合、データをフェッチするスレッドは、複雑なメモリモデルの理由から、最新の値を取得しないことがあります。

しかし、私はこれを回避する方法についてはわかりません。あなたはラムダ式と拡張メソッドで奇妙なことをすることができますが、それは過度のIMOだろう。

本当にのいずれかがスレッドセーフであることを強く検討する必要があります。これは正しいことかもしれませんが、通常、ほとんどの型はスレッドセーフである必要はありません。スレッディングについて直接知る必要があるのはほんのわずかですが、ロックを行っているオブジェクトではなく、オブジェクトを使用している間に適切なロックを解除します。それはあなたが何をしているのかに依存します。

場合によっては、変更可能なタイプを使用することもできます。変更することが可能な場合は便利ですが、別のスレッドで変更を確認する必要がある場合はのボラティリティまたは同期のソートが必要です。

+0

+1絶対に正しいです。そのような場合(単純なgetter/setterのシナリオ)、私はInterlockedクラスを使用します。 –

+0

@Toro:その時点では、異なるプロパティの種類について別々に考える必要があり、他のいくつかのプロパティではロックを使用する必要があります。もう一つの選択肢は揮発性変数です。個人的には、ボトルネックが見られる場合を除いて、私は一貫性のあるロック方法を適用することをお勧めします。 –

+0

@Jon Skeet:クラス内の各プロパティに同じロックオブジェクトを使用するのは正しいですか?別のスレッドでYが更新されているときにXへのアクセスをロックするのに気をつけますか? –

3

「イネーブラー」ではないが、これが間違いなくあなたが望むデザインであると判断した場合、これらのプロパティーを繰り返し入力すると、いくつかのキーストロークを保存してスピードアップするコードスニペットそれらを追加するプロセス。

<?xml version="1.0" encoding="utf-8" ?> 
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> 
    <CodeSnippet Format="1.0.0"> 
     <Header> 
      <Title>prop</Title> 
      <Shortcut>propso</Shortcut> 
      <Description>Locking property for SO</Description> 
      <Author>TheMissingLinq</Author> 
      <SnippetTypes> 
       <SnippetType>Expansion</SnippetType> 
      </SnippetTypes> 
     </Header> 
     <Snippet> 
      <Declarations> 
       <Literal> 
        <ID>type</ID> 
        <ToolTip>Property type</ToolTip> 
        <Default>int</Default> 
       </Literal> 
       <Literal> 
        <ID>property</ID> 
        <ToolTip>Property name</ToolTip> 
        <Default>MyProperty</Default> 
       </Literal> 
       <Literal> 
        <ID>field</ID> 
        <ToolTip>Field Name</ToolTip> 
        <Default>myField</Default> 
       </Literal> 
      </Declarations> 
      <Code Language="csharp"> 
      <![CDATA[private $type$ $field$; 
       public $type$ $property$ 
       { 
        get 
        { 
         lock(locker) { return this.$field$; } 
        } 
        set 
        { 
         lock(locker) { this.$field$ = value; } 
        } 
       } 
      $end$]]> 
      </Code> 
     </Snippet> 
    </CodeSnippet> 
</CodeSnippets> 
関連する問題