如何使用 C# 将同一个实例共享给多个线程中的所有派生 类?

How can I share the same instance to all derived classes in multiple threads with C#?

我在 C# 中使用 命令模式。 有一个 class 包含一些名为 RequiredData.

的属性
public class RequiredData
{
  public Class1 class1 { get; set; }
  public int value1 {get; set;}
}

有一个抽象 class BaseCommand 并且有一些派生的 class 像 command1 , command2 etc.

   abstract class BaseCommand : ICommand { }

这些命令会执行一些操作,例如:

command1.Execute();
command2.Execute();

我希望在整个过程中有一个共享的 RequiredData 对象,它可以在所有命令中更新和使用。 例如:

在 command1 Execute 方法中访问 value1,如:

RequiredData.Value1 = 5

然后在 command2 Execute 方法中使这个值像

    var k = RequiredData.Value1 //and be 5..
or RequiredData.Class1.something = "something"

我在基地试过这个 class:

  abstract class BaseCommand : ICommand
  {
      //or protected and not private...
      public static RequiredData RequiredData = new RequiredData();
   }

这是线程安全的吗?

线程安全解决方案需要进行哪些更改?

您可以使用多种方法解决此问题。

  • 将共享实例传递给构造函数
  • 单例 pattern/static 可以提供帮助,但限制更多。

提醒一下,如果你在不同的线程上使用class,你需要注意线程安全。


通常我会避免使用可以被多个线程 readed/writed 的静态对象。我建议你尝试摆脱这个。

但是...您需要确定 object/reference 类型无法从外部访问。

喜欢:

// you could create the locking in this class, but the class1 property is a
// reference type, so just locking in the property is not enought, it
// goes wrong when the Class1 has properties itself. (then these will be
// altered outside the lock..
// I choose to wrap the whole object and only returning value types

public class RequiredData
{
    public Class1 class1 { get; set; }
    public int value1 {get; set;}
}

abstract class BaseCommand : ICommand
{
    // protected.. should not be accessable from the outside..!
    protected static RequiredData RequiredData = new RequiredData();

    public int GetValue()
    {
        lock(RequiredData)
            return RequiredData.value1;
    }

    public void SetValue(int value)
    {
        lock(RequiredData)
            RequiredData.value1 = value;
    }

// or you could wrap this in a property

    public int Value
    {
        get { return lock(RequiredData) RequiredData.value1; }
        set { lock(RequiredData) RequiredData.value1 = value; }
    }


    public string GetSomething()
    {
        // try to avoid returning reference types, but the can be referenced from outside the object.
        lock(RequiredData)
            return RequiredData.Class1.something;
    }
}

所以锁定应该在 BaseCommand 内。而 BaseCommand 应该负责与 RequiredData 进行通信。 (因此没有其他对象可以引用 RequiredData)

就像我说的:多线程/静态read/writer = 玩火。


如果你有很多 readers/writers 你应该看看 ReaderWriterLock(Slim)。因为多个线程可以同时读取并且只有一个写入器处于活动状态。