如何使用 Interlocked.Add 更新我的模型计数器值
How to update my model counter value using Interlocked.Add
所以我有这个模型:
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
class 我想更新我的 class Total
属性 但我需要它是线程安全的因为很多线程同时做:
public static void UpdateTotal(Container container, int value)
{
Interlocked.Add(ref container.Total, value);
}
并得到这个错误:
A property or indexer may not be passed as an out or ref parameter
您应该在 Container
:
中创建一个 Add
方法
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);
添加到 setter 中,因为所需的使用模式仍然是非线程保存:
var total = container.TotalPackets; // #1
total += 10; // #2
container.TotalPackets = total; // #3
#3 中新总值的设置本身是线程安全的,但在#1 和#3 之间,其他线程可能已经更改了总值。如果我们考虑两个线程并且开始总数为 10,则可能会发生以下执行顺序:
- 线程 1 - #1 ==> 读取 10
- 线程 1 - #2 ==>
total
设置为 20
- 线程 2 - #1 ==> 读取 10,因为线程 1 尚未 运行 #3
- 线程 1 - #3 ==>
TotalPackets
设置为 20(初始 10 + 来自 #2/2 的 10。)
- 线程 2 - #2 ==>
total
在 3 时设置为 20。它仍然是 10
- 线程 2 - #3 ==>
TotalPackets
再次设置为 20 => boom ;-)
所以我有这个模型:
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
class 我想更新我的 class Total
属性 但我需要它是线程安全的因为很多线程同时做:
public static void UpdateTotal(Container container, int value)
{
Interlocked.Add(ref container.Total, value);
}
并得到这个错误:
A property or indexer may not be passed as an out or ref parameter
您应该在 Container
:
Add
方法
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);
添加到 setter 中,因为所需的使用模式仍然是非线程保存:
var total = container.TotalPackets; // #1
total += 10; // #2
container.TotalPackets = total; // #3
#3 中新总值的设置本身是线程安全的,但在#1 和#3 之间,其他线程可能已经更改了总值。如果我们考虑两个线程并且开始总数为 10,则可能会发生以下执行顺序:
- 线程 1 - #1 ==> 读取 10
- 线程 1 - #2 ==>
total
设置为 20 - 线程 2 - #1 ==> 读取 10,因为线程 1 尚未 运行 #3
- 线程 1 - #3 ==>
TotalPackets
设置为 20(初始 10 + 来自 #2/2 的 10。) - 线程 2 - #2 ==>
total
在 3 时设置为 20。它仍然是 10 - 线程 2 - #3 ==>
TotalPackets
再次设置为 20 => boom ;-)