关于c#:锁定类成员与在类的方法中初始化该对象?

Lock on an class member vs having that object initialized in class' method?

因此,我有此服务,我们将其称为" MyService "。 MyService有一个公共方法,即" executeBatchJob ",顾名思义,它将执行一个batchJob,简而言之,从数据库中检索一些数据,在某个时候,我有一个非常类似于实体的对象,带有ID和记录列表。在我的方法executeBatchJob中,进行了一些检查,当满足某些条件时,将实体写入某个位置并重新初始化(新ID,不同的记录),但是请注意,它发生在executeBatchJob调用的私有方法中。在其他条件下,采用不同的私有方法,记录将添加到该实体保存的记录列表中。

我的问题是:由于服务可能由多个过程调用:将实体声明为类成员(私有只读)并在需要时将其锁定,然后使用一种可以清理实体的方法更好吗?下一步的状态。还是最好在我的方法executeBatchJob中声明并使用此对象,但是通过所有私有方法拖动该对象,因为该对象的状态可能会在多个"级别"变化?

为了向您说明我在解释什么:

这是myEntity:

1
2
3
4
5
6
7
8
9
10
11
public class MyEntity
{
 public int Id { get; set; }
 public List<Record> Records { get;  set; }

 public void CleanUp(int newId)
 {
     Id = newId;
     Records.Clear();
 }
}

这是带锁的myService:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class MyService : IMyService
{
 private readonly MyEntity _myEntity;

 public MyService()
 {
     _myEntity = new MyEntity();
 }

 public void executeBatchJob(int batchId)
 {
     //some code
     lock(_myEntity)
     {
        // More code and call to some private method
        _myEntity.CleanUp();
     }

     // still more code
 }
}

或使用第二个选项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class MyService : IMyService
{

 public MyService()
 {
 }

 public void executeBatchJob(int batchId)
 {
     MyEntity myEntity = new MyEntity();

     APrivateMethodInExecuteBatchJob(myEntity);
     // more code

 }

 private returnResult APrivateMethodInExecuteBatchJob(MyEntity myEntity)
 {
      // Some manipulation of myEntity
      // some code, with another call to a private method with myEntity, and manipulation of myEntity

      // ... write the entity
      myRepository.write(myEntity);

 }
}

据我所知,要提供更多上下文,每次将写入实体时,都必须对其进行清理,在第二种选择中,我可以做一个" new MyEntity()"(这使得从业务angular来看更有意义)。

对我来说,第二种解决方案是更合理,更合理的方法,但是,我将有几个私有方法来移动对象,有时只是将其传递给另一个私有方法而无需"传递"之外的任何其他操作。转到其他私有方法...根本不干净...

这就是为什么我需要您的建议/意见。


如果不应该保留实体的状态,那么我认为在选项2中拥有幂等方法要好得多。如果可以使这些方法静态化,那么您将得到一个简单得多的体系结构。

您已经确定需要将资源锁定在选项1中,并且只要在清理过程中丢弃该状态就不会出现令人头疼的问题。

我唯一能看到类似选项1的原因是该实体是由使用之间没有清除的交易建立的,还是该实体由于某种原因创建起来非常昂贵。


使用IDisposable界面,其目的正是您正在做的事情

1
public class MyEntity: IDisposable;

然后,您可以将第二个选项与using关键字一起使用。

您可以在此处查看有关实施方式和方法的示例。 https://docs.microsoft.com/zh-cn/dotnet/standard/garbage-collection/implementing-dispose

示例代码:

1
2
3
4
5
6
7
8
9
10
public void executeBatchJob(int batchId)
{

    using (vMyEntity myEntity = new MyEntity();)
    {
       APrivateMethodInExecuteBatchJob(myEntity);
       // more code
    }

}

通常,尽量避免在不需要时使用锁。它可能会创建竞争条件,这将使您的应用程序响应速度变慢。