在文档这里中:“这个类的方法有助于防止在线程更新其他线程可以访问的变量时调度程序切换上下文时发生的错误……”
此外,对这个问题状态的回答“在任意数量的核心或CPU上,互锁方法同时是安全的”,这似乎相当清楚。
基于上述,我认为Interlocked.Add()足以让多个线程对变量进行加法。显然我错了或者我使用的方法不正确。在下面的可运行代码中,当Run()完成时,我期望Downloader.ActiveRequestCount为零。如果我不锁定对Interlocked.Add的调用,就会得到一个随机的非零结果。Interlocked.Add()的正确用法是什么?
class Program
{
private Downloader downloader { get; set; }
static void Main(string[] args)
{
new Program().Run().Wait();
}
public async Task Run()
{
downloader = new Downloader();
List<Task> tasks = new List<Task>(100);
for (int i = 0; i < 100; i++)
tasks.Add(Task.Run(Download));
await Task.WhenAll(tasks);
Console.Clear();
//expected:0, actual when lock is not used:random number i.e. 51,115
Console.WriteLine($"ActiveRequestCount is : {downloader.ActiveRequestCount}");
Console.ReadLine();
}
private async Task Download()
{
for (int i = 0; i < 100; i++)
await downloader.Download();
}
}
public class Downloader :INotifyPropertyChanged
{
private object locker = new object();
private int _ActiveRequestCount;
public int ActiveRequestCount { get => _ActiveRequestCount; private set => _ActiveRequestCount = value; }
public async Task<string> Download()
{
string result = string.Empty;
try
{
IncrementActiveRequestCount(1);
result = await Task.FromResult("boo");
}
catch (Exception ex)
{
Console.WriteLine("oops");
}
finally
{
IncrementActiveRequestCount(-1);
}
return result;
}
public void IncrementActiveRequestCount(int value)
{
//lock (locker) // is this redundant
//{
_ActiveRequestCount = Interlocked.Add(ref _ActiveRequestCount, value);
//}
RaisePropertyChanged(nameof(ActiveRequestCount));
}
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged([CallerMemberNameAttribute] string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
#endregion
}发布于 2018-03-21 20:30:54
替换
_ActiveRequestCount = Interlocked.Add(ref _ActiveRequestCount, value);使用
Interlocked.Add(ref _ActiveRequestCount, value);Interlocked.Add是线程安全的,并接受一个ref参数,这样它就可以安全地执行任务。此外,还执行(不必要的)不安全分配(=)。只要把它移开。
https://stackoverflow.com/questions/49415894
复制相似问题