Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#如何与第三方锁定抽象类_C#_Multithreading_Abstract - Fatal编程技术网

C#如何与第三方锁定抽象类

C#如何与第三方锁定抽象类,c#,multithreading,abstract,C#,Multithreading,Abstract,导言 我有一个公共抽象类,带有一个抽象方法,我想从工作线程调用它 调用该方法时,应锁定相应的实例,以防止在计算过程中更改状态 我只想使用抽象类,因为继承器的实现是由第三方完成的 public abstract class MyClass { public abstract MyResult GetData(); } 问题 我的库被第三方使用,我必须假设他们对库的内部实现一无所知 P>我不想强迫他们去研究我的类的文档,直到他们能够实现自己的继承者,因为我认为这个坏的形式。 我的方法 我

导言

我有一个公共抽象类,带有一个抽象方法,我想从工作线程调用它

调用该方法时,应锁定相应的实例,以防止在计算过程中更改状态

我只想使用抽象类,因为继承器的实现是由第三方完成的

public abstract class MyClass
{
    public abstract MyResult GetData();
}
问题

我的库被第三方使用,我必须假设他们对库的内部实现一无所知

<> P>我不想强迫他们去研究我的类的文档,直到他们能够实现自己的继承者,因为我认为这个坏的形式。

我的方法

我的第一个想法是在类中添加一个受保护的锁对象,并在调用该方法时锁定它

然而,为了使它有用,第三方也必须锁定它,从而了解它

因为我不想强迫第三方了解内部情况,所以我不喜欢这个选项

public abstract class MyClass
{
    protected readonly object myLock = new object();

    public MyResult GetData()
    {
        MyResult result;

        lock(myLock)
        {
            result = GetDataInternal();
        }

        return result;
    }

    protected abstract MyResult GetDataInternal();
}
背景

我正在处理一个数据管道,它在一个单独的线程上运行

此管道以特定格式请求数据,并在后台进行处理

提供数据可能需要一些时间,并且提供的数据依赖于对象的属性

在本例中,它是三维模型的准备管道

问题

如何在不知道其实现的情况下锁定整个对象

如果没有这样的方法,那么对于这个问题是否有一个一致的模式或类似的东西

我的库被第三方使用,我必须假设他们对库的内部实现一无所知。 (..) 调用该方法时,应锁定相应的实例,以防止在计算过程中更改状态

我认为最好的办法是。。让他们知道,并确保他们知道他们对此负责。您可以轻松地使其直观,而无需(大量)文档

考虑将抽象类更改为以下内容:

public interface ILockable
{
    void FreezeDataForCalculations();
    void ThawAfterCalculations();
}

public abstract class MyBaseClass<T> where T:ILockable
{
    public abstract T GetData();
}
公共接口ILockable
{
计算数据无效();
计算后无效();
}
公共抽象类MyBaseClass,其中T:ILockable
{
公共摘要T GetData();
}
用法:

public class MyThingie : MyBaseClass<TheActualData>
{
}

public class TheActualData : ILockable
{
    public string Foo {get;set;}

    public void FreezeDataForCalculations() { ...???...}
    public void ThawAfterCalculations() { ....???.... }
}
公共类MyThingie:MyBaseClass
{
}
公共类实际数据:i可锁定
{
公共字符串Foo{get;set;}
public void FreezeDataForCalculations(){…?…}
公共计算({…?…}
}
现在,您有效地确保:

  • 无论谁想要实现它,都必须提供自己的类型,实现额外的接口
  • 无论谁实现了这个额外的接口都会注意到这两种方法,他们至少会想到“wtf”,并且会立即理解,或者会尝试查阅文档
  • 您不锁定数据,类的创建者负责锁定
  • 现在的实现者可以选择在何时实际实现冻结/解冻对,或者将它们保留为空,只需编写自己的代码即可,同时不修改数据
  • 您的代码现在必须适当地调用“冻结”和“解冻”,并且可以假设实现者做了预期的事情

相反,如果你不能假设他确实做到了,那就改变你库的API,不允许使用用户定义的类型,并将API限制为你自己的类型,你可以确保它能发挥作用。

只是一个评论。强制从您的类型继承的人阅读文档并遵循您制定的规则,这在形式上是不错的,这是绝对必要的。当然,你应该让他们很容易陷入“成功的陷阱”,但是如果你想让他们从你的类型继承,你就不能让类型万无一失。据你所知,他们可以实现返回你所期望的负面结果的方法,使用这些子类型对任何代码的工作都是一个大麻烦。如果代码不关心锁,没有一个通用锁可以“锁定代码”执行。换句话说,如果某些代码访问对象时没有锁定,而某些代码使用锁定,那么您无法神奇地让第一段代码关心锁定而不更改它。您可以关闭对象,以便只提供线程安全访问,例如只提供其内部的快照,但这也需要更改使用您的类型的任何第三方代码。您是对的,必须阅读文档。但在这里,我不喜欢这个要求,因为直觉上大多数人都无法识别myLock属性。我不喜欢(在大多数情况下)只有在阅读文档时才正确使用的实现。还有一个注意事项-您可以将
myLock
设置为私有。它仅由您的公共方法使用。继承类的人不需要知道它的存在,他们需要知道它的存在,因为现在唯一要做的就是防止多次同时调用“GetDataInternal”。然而,现在它并不阻止其他线程访问实例。这既美观又简单。如果有人忽视了这一点,那显然是他们自己的错。对我来说这是个很好的解决办法。非常感谢。我认为这是从原来的设计倒退了一步。问题是如何隐藏锁定行为。OP的代码就是这么做的。这恰恰相反——暴露了对锁的需要,并让消费者负责。也许还有一种方法可以改进原始版本,但它正在实现目的。继承类的人可以填充所需的功能,但甚至不需要知道是否存在锁定。从另一个角度看,这需要有人给我打电话