C # Синхронизированный объект - дублированный код с написанием аксессоров - PullRequest
3 голосов
/ 19 марта 2009

Мне нравится использовать объекты, которые синхронизируются, используя закрытый объект, который блокируется при изменении свойства. Есть ли общий способ достичь этого? Мой код всегда выглядит так для каждого свойства (с одним объектом блокировки)

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

Является ли ты более простым способом достижения поточно-ориентированной модификации свойств.

Ответы [ 3 ]

8 голосов
/ 19 марта 2009

Ваш код не должен выглядеть так - вы должны также заблокировать get . В противном случае потоки, извлекающие данные, могут не получить самое последнее значение по причинам сложной модели памяти.

Но нет, я не знаю никаких способов обойти это. Вы можете делать странные вещи с помощью лямбда-выражений и методов расширения, но это будет излишним ИМО.

Вы также должны тщательно продумать, действительно ли вы хотите, чтобы отдельные свойства были поточно-ориентированными. Это может быть правильным, но я обнаружил, что обычно мне не нужно, чтобы большинство типов было поточно-ориентированным. Только несколько типов должны непосредственно знать о многопоточности, и они затем снимают соответствующие блокировки, пока они используют объект, а не объект, выполняющий саму блокировку. Хотя это зависит от того, что вы делаете.

Другой альтернативой для некоторых случаев является использование неизменяемых типов - это хорошо, когда вы можете это сделать, хотя если вам нужен один поток, чтобы увидеть изменения, сделанные в другом, вам понадобится некоторая разновидность изменчивости синхронизации.

3 голосов
/ 19 марта 2009

Не для того, чтобы быть «активатором», но если вы решите, что это именно тот дизайн, который вам нужен, и вам придется вводить эти свойства многократно, возможно, вы захотите сэкономить несколько нажатий клавиш и написать небольшой фрагмент кода, чтобы ускорить процесс их добавления.

    <?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>
2 голосов
/ 25 марта 2009

Я продолжаю удивляться тому, что C # может делать с новыми функциями C # 3.0. Я собирался выбросить что-то там, что я думал, будет так себе, но оказывается, что лучше, чем я надеялся. Вот это.

Сделайте объект для хранения всех значений (давайте просто назовем его «держателем значения» ... не путать с любым другим использованием этого термина). Он не имеет ничего, кроме автоматических свойств C #. Затем создайте другой объект, который дает доступ владельцу стоимости. Назовите второй объект «SynchronicityHandler» (отнюдь не полный термин, но он поможет понять концепцию).

Пусть SynchronicityHandler выполняет блокировку. Теперь это может быть общим. Итак, вот что вы получите:

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);
          }
     }
}

Вот пример того, как бы вы назвали это:

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".

Действительно, теперь, когда я думаю об этом, «держатель стоимости» не должен быть просто автоматическими свойствами. Это может быть любой объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...