Streaming Safe Field

I have a common field and a property that encapsulates it:

T item;

public T Item
{
    get { return item; }
    set { item = value; }
}

The problem is that this property can be written from one stream and read from several streams at the same time. And if Tit's structor long, readers can get results that are the old value of the part and part of the new value. How can I prevent this?

I tried using volatile, but this is not possible:

An unstable field cannot be of type "T".

Since this is a simpler example of the code that I have already written that uses ConcurrentQueue<T>, I thought about using it here:

ConcurrentQueue<T> item;

public T Item
{
    get
    {
        T result;
        item.TryPeek(out result);
        return item;
    }

    set
    {
        item.TryEnqueue(value);
        T ignored;
        item.TryDequeue(out ignored);
    }
}

It will work, but it seems to me that this is a difficult solution for something that should be simple.

, , , .

a set get, , get .

+5
3

, T.

class T, . . , .

. , .

T - , ( 12.5 #, ):

: bool, char, byte, sbyte, short, ushort, uint, int, float reference . , . , , , , , . , , read-modify-write, , .

, , , /, , ( , T).

T, - lock statement ( , ).

, lock (, Monitor ) , SpinLock structure, , Monitor :

T item;

SpinLock sl = new SpinLock();

public T Item
{
    get 
    { 
        bool lockTaken = false;

        try
        {
            sl.Enter(ref lockTaken);
            return item; 
        }
        finally
        {
            if (lockTaken) sl.Exit();
        }
    }
    set 
    {
        bool lockTaken = false;

        try
        {
            sl.Enter(ref lockTaken);
            item = value;
        }
        finally
        {
            if (lockTaken) sl.Exit();
        }
    }
}

, SpinLock , Monitor, ; , , /, ( , ).

, , , , , (lock SpinLock).

+3

Interlocked, , , T . ( , .)

, . , . , , , .

, , - - .

+3

?

- . , get, . , , set . , , .

I, 12.6.6 CLI : " CLI , , , , ."

, . , , - :

Private T _item;
public T Item
{
    get
    {
        return _item;
    }

    set
    {
        _item = value
    }
}

An example is if you want to stick to common material and use it for everything. The approach is to use a helper class-media. This significantly reduces performance, but is not blocked.

Public Foo
{
    Private Carrier<T> 
    {
        T _item
    }

    Private Carrier<T> _item;
    public T Item
    {
        get
        {
            Dim Carrier<T> carrier = _item;
            return carrier.item;
        }



set
    {
        Dim Carrier<T> carrier = new Carrier<T>();
        carrier.item = value;
        _item = carrier;
    }
}

}

This way you can ensure that you always use reference types and that your access is blocked. The disadvantage is that all given operations create garbage.

-2
source

All Articles