C# 并发字典对象 Read/Update 线程安全问题

C# Concurrent Dictionary Object Read/Update Thread Safety Question

在下面的代码中,我有一个并发字典,用于存储单个 key/value 对,其中值是字符串集合。

我将从不同的线程读取和更新这一 key/value 对中的字符串。

我知道如果一个线程在另一个线程可能完成读取之前更改了一个值,则并发字典不是完全线程安全的。但同样我不确定字符串值是否真的涉及到这个主题,有人可以建议一下吗?

另外值得一提的是,虽然我把这个“GetRunTimeVariables”方法放在一个接口中进行依赖注入,但由于应用程序启动和OIDC事件标志的阶段,我实际上不能一直使用DI来访问这个方法in/out 其中我需要访问 classes 中不能使用依赖注入的字典值,所以本质上我可以在应用程序的整个生命周期中根据需要从 nay 访问这本字典。

最后,我不太确定将此方法推入接口是否有任何好处,另一个选项只是在每次我需要时新建一个对此 class 的引用,一些想法这将不胜感激。

public class RunTimeSettings : IRunTimeSettings
{
    // Create a new static instance of the RunTimeSettingsDictionary that is used for storing settings that are used for quick
    // access during the life time of the application. Various other classes/threads will read/update the parameters.
    public static readonly ConcurrentDictionary<int, RunTimeVariables> RunTimeSettingsDictionary = new ConcurrentDictionary<int, RunTimeVariables>();

    public object GetRunTimeVariables()
    {
        dynamic settings = new RunTimeVariables();

        if (RunTimeSettingsDictionary.TryGetValue(1, out RunTimeVariables runTimeVariables))
        {
            settings.Sitename = runTimeVariables.SiteName;                
            settings.Street = runTimeVariables.Street;
            settings.City = runTimeVariables.City;
            settings.Country = runTimeVariables.Country;
            settings.PostCode = runTimeVariables.PostCode;
            settings.Latitude = runTimeVariables.Latitude;
            settings.Longitude = runTimeVariables.Longitude;
        }

        return settings;
    }
}

Class 对于字符串值:

public class RunTimeVariables
{
    public bool InstalledLocationConfigured { get; set; }
    public string SiteName { get; set; }
    public string Street { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
    public string PostCode { get; set; }
    public string Latitude { get; set; }
    public string Longitude { get; set; }
}

System.String 类型(C# 的经典 strings)是不可变的。没有人可以修改 String 的“内容”。任何人都可以将 属性 引用 不同 String.

但实际上,您在这里遇到的唯一问题是各种值可能会不同步。您有各种相关的属性。如果一个线程正在修改对象而另一个线程正在读取它,则读取线程可以看到“旧”版本的一些属性和“新”版本的一些属性。如果对象一旦写入 ConcurrentDictionary 没有改变(至少作为业务规则是“不可变的”),这不是一个大问题。显然,正确的解决方案是让 RuntimeVariables 成为一个不可变对象(仅由 readonly 字段组成,例如在实例化时初始化)