gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 22:46:56 24 4
gpt4 key购买 nike

来自文档 here :“此类的方法有助于防止在线程正在更新可由其他线程访问的变量时调度程序切换上下文时可能发生的错误...”

此外,对 this question 的回答声明“互锁方法在任何数量的内核或 CPU 上都是同时安全的”,这似乎很清楚。

基于以上内容,我认为 Interlocked.Add() 足以让多个线程对一个变量进行加法运算。显然我错了,或者我使用的方法不正确。在下面的可运行代码中,我希望 Downloader.ActiveRequestCount 在 Run() 完成时为零。如果我不锁定对 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
}

最佳答案

替换

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

Interlocked.Add(ref _ActiveRequestCount, value);

Interlocked.Add 是线程安全的,并带有一个 ref 参数,因此它可以安全地进行赋值。您另外执行了(不必要的)不安全赋值 (=)。只需将其删除即可。

关于c# - 如何正确使用 Interlocked.Add()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49415894/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com