C# 如何正确使用Interlocked.Add()?

C# 如何正确使用Interlocked.Add()?,c#,multithreading,C#,Multithreading,从文档中可以看出:“当一个线程正在更新一个可被其他线程访问的变量时,当调度器切换上下文时,此类方法有助于防止可能发生的错误…” 此外,对“联锁方法在任何数量的内核或CPU上都是同时安全的”的回答似乎非常清楚 基于上述内容,我认为Interlocked.Add()足以让多个线程对一个变量进行加法。显然我错了,或者我使用的方法不正确。在下面的可运行代码中,我希望在Run()完成时Downloader.ActiveRequestCount为零。如果我没有锁定对Interlocated.Add的调用,我

从文档中可以看出:“当一个线程正在更新一个可被其他线程访问的变量时,当调度器切换上下文时,此类方法有助于防止可能发生的错误…”

此外,对“联锁方法在任何数量的内核或CPU上都是同时安全的”的回答似乎非常清楚

基于上述内容,我认为Interlocked.Add()足以让多个线程对一个变量进行加法。显然我错了,或者我使用的方法不正确。在下面的可运行代码中,我希望在Run()完成时Downloader.ActiveRequestCount为零。如果我没有锁定对Interlocated.Add的调用,我会得到一个随机的非零结果。Interlocked.Add()的正确用法是什么

类程序
{
私有下载程序下载程序{get;set;}
静态void Main(字符串[]参数)
{
新程序().Run().Wait();
}
公共异步任务运行()
{
downloader=新的downloader();
列表任务=新列表(100);
对于(int i=0;i<100;i++)
tasks.Add(Task.Run(下载));
等待任务。何时(任务);
Console.Clear();
//预期值:0,未使用锁时的实际值:随机数,即51115
WriteLine($“ActiveRequestCount为:{downloader.ActiveRequestCount}”);
Console.ReadLine();
}
专用异步任务下载()
{
对于(int i=0;i<100;i++)
等待downloader.Download();
}
}
公共类下载程序:INotifyPropertyChanged
{
私有对象锁定器=新对象();
私有int_ActiveRequestCount;
public int ActiveRequestCount{get=>\u ActiveRequestCount;private set=>\u ActiveRequestCount=value;}
公共异步任务下载()
{
字符串结果=string.Empty;
尝试
{
递增的ActiveRequestCount(1);
结果=等待任务。FromResult(“boo”);
}
捕获(例外情况除外)
{
Console.WriteLine(“oops”);
}
最后
{
递增的ActiveRequestCount(-1);
}
返回结果;
}
public void IncrementActiveRequestCount(int值)
{
//锁(储物柜)//这是多余的吗
//{
_ActiveRequestCount=Interlocked.Add(ref\u ActiveRequestCount,value);
//}
RaisePropertyChanged(nameof(ActiveRequestCount));
}
#区域INotifyPropertyChanged实现
公共事件属性更改事件处理程序属性更改;
public void RaisePropertyChanged([CallerMemberNameAttribute]string propertyName=”“)=>PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
#端区
}
更换

_ActiveRequestCount = Interlocked.Add(ref _ActiveRequestCount, value);


Add是线程安全的,并采用
ref
参数,因此它可以安全地执行赋值。您还执行了(不必要的)不安全分配(
=
)。只需删除它。

您不需要将“添加”的结果分配回该字段。字段_ActiveRequestCount由该方法递增,这就是为什么它需要一个ref.OMG。谢谢你,迈克。
_ActiveRequestCount = Interlocked.Add(ref _ActiveRequestCount, value);
Interlocked.Add(ref _ActiveRequestCount, value);