c#锁定对象共享的公共方法和事件回调代码

本文关键字:方法 事件 回调 代码 锁定 对象 共享 | 更新日期: 2023-09-27 18:10:14

关于锁的问题,文本指的是下面的示例代码…我有一个类Class1,它提供了一个名为Class1Resources的公共List属性。Class1中的2个方法提供了Class1Resources的基本查询功能。此外,Class1还订阅了来自不同服务的事件,该服务提供通知Class1应该更新这个Class1Resources对象。

我的问题是,应该在哪里实现锁定,以便在ExternalAppCallback执行时阻止查询Class1Resources的2个公共方法,从而确保查询方法始终使用最新的数据?我在ExternalAppCallback中注释的代码是正确的方法吗?

public class Class1
{
    public List<Resource> Class1Resources { get; private set; }
    public Class1()
    {
        // subscribe to external app event, with callback = ExternalAppCallback
    }
    private void ExternalAppCallback(List<Resource> updatedResourceList)
    {
        // do I put the lock here as in the code below?
        //lock(someObject)
        //{
        //    Class1Resources = new List<Resource>(updatedResourceList);
        //}
        Class1Resources = new List<Resource>(updatedResourceList);
    }
    public List<Resource> GetResourcesByCriteria1(string criteria1)
    {
        return Class1Resources.Where(r => r.Criteria1 == criteria1).ToList();
    }
    public List<Resource> GetResourcesByCriteria2(string criteria2)
    {
        return Class1Resources.Where(r => r.Criteria2 == criteria2).ToList();
    }
}

c#锁定对象共享的公共方法和事件回调代码

我将您的问题解释为"如何有效地使Class1Resources线程安全?"因此,我建议使用经典的lock,或者,如果您希望写入/更改很少,则建议使用ReaderWriterLockSlim。以下是如何在类中使用lock来确保线程安全/数据一致:

public class Class1
{
    // Here's your object to lock on
    private readonly object _lockObject = new object();
    // NOTE: made this private to control how it is exposed!
    private List<Resource> Class1Resources = null;
    public Class1()
    {
        // subscribe to external app event, with callback = ExternalAppCallback
    }
    private void ExternalAppCallback(List<Resource> updatedResourceList)
    {
        // Setting a reference is always atomic, no need to lock this
        Class1Resources = new List<Resource>(updatedResourceList);
    }
    // Your new method to expose the list in a thread-safe manner
    public List<Resource> GetResources()
    {
        lock (_lockObject)
        {
            // ToList() makes a copy of the list versus maintaining the original reference
            return Class1Resources.ToList();
        }
    }
    public List<Resource> GetResourcesByCriteria1(string criteria1)
    {
        lock (_lockObject)
        {
            return Class1Resources.Where(r => r.Criteria1 == criteria1).ToList();
        }
    }
    public List<Resource> GetResourcesByCriteria2(string criteria2)
    {
        lock (_lockObject)
        {
            return Class1Resources.Where(r => r.Criteria2 == criteria2).ToList();
        }
    }
}

注意,在这个解决方案中,任何调用属性的getter的东西都不会使用锁,因此会导致线程安全问题。这就是为什么我更改代码使其成为私有成员。