如何使用Interlocked.Add更新我的模型计数器值

时间:2018-02-08 09:59:16

标签: c# interlocked

所以我有这个模型:

public class Container : INotifyPropertyChanged
{
    private int _total;
    private static InjectionContainer _mainContainer = new InjectionContainer();
    private static InjectionContainer _secondContainer = new InjectionContainer();
    private ObservableCollection<MyData> _files = new ObservableCollection<MyData>();

    public int TotalPackets
    {
        get { return _total; }
        set
        {
            _total = value;
            OnPropertyChanged("Total");
        }
    }

    public ObservableCollection<MyData> List
    {
        get { return _files; }
        set { _files = value; }
    }
}

在这个Container类之外我想更新我的类Total属性,但我需要它是线程安全的,因为很多线程同时执行它:

public static void UpdateTotal(Container container, int value)
{
    Interlocked.Add(ref container.Total, value);
}

得到了这个错误:

  

属性或索引器不能作为out或ref参数传递

1 个答案:

答案 0 :(得分:4)

您应该在Add

中创建Container方法
public class Container : INotifyPropertyChanged
{
    private int _total;
    private static InjectionContainer _mainContainer = new InjectionContainer();
    private static InjectionContainer _secondContainer = new InjectionContainer();
    private ObservableCollection<MyData> _files = new ObservableCollection<MyData>();

    public int TotalPackets
    {
        get { return _total; }
    }

    public ObservableCollection<MyData> List
    {
        get { return _files; }
        set { _files = value; }
    }

    public void AddTotal(int value)
    {
        Interlocked.Add(ref _total, value);
        OnPropertyChanged("TotalPackets");
    }
}

您无法将Interlocked.Add(ref _total, value);添加到设置器中,因为所需的使用模式仍然是非线程保存的:

var total = container.TotalPackets; // #1
total += 10; // #2
container.TotalPackets = total; // #3

在#3中设置新的总值本身就是线程安全的,但在#1和#3之间,其他一些线程可能已经改变了总值。如果我们想到两个线程并且起始总数为10,则可能发生以下执行顺序:

  1. 主题1 - #1 ==&gt;阅读10
  2. 主题1 - #2 ==&gt; total设置为20
  3. 主题2 - #1 ==&gt;读取10,因为线程1尚未运行#3
  4. 主题1 - #3 ==&gt; TotalPackets设置为20(最初10 + 10来自#2/2。)
  5. 主题2 - #2 ==&gt; total设置为20,因为它仍为10
  6. 主题2 - #3 ==&gt; TotalPackets再次设置为20 =&gt;繁荣; - )