4

我有一个反序列化 Xml 文档并从中创建对象的函数。

我希望将对象存储到缓存中,因此每次需要从中获取数据时我都不必反序列化 xml。

public class XMLDeserializer
{
    public event OnElementDeserialized OnElementDeserializedCallback;

    public void DeserializeXml(string xmlPath)
    {
        // implementation
    }
}

public class XMLDeserializerFacade
{
    private static object _lockObject = new object();

    private XMLDeserializer xmlDeserializer;
    private ICacheProvider cacheProvider;
    public XMLDeserializerFacade(XMLDeserializer xmlDeserializer, ICacheProvider cacheProvider)
    {
        this.xmlDeserializer = xmlDeserializer;
        this.cacheProvider = cacheProvider;

        xmlDeserializer.OnElementDeserializedCallback += delegate(object element)
        {
            cacheProvider.Add("uniqueKey", element);
            // is here in lock as well or i have to lock it again?
        };
    }

    public void DeserializeXml(string xmlPath)
    {
        lock(_lockObject)
        {
            xmlDeserializer.DeserializeXml(xmlPath);

            // From here it will go to
            // cacheProvider.Add("uniqueKey", element);  callback
        }
    }
}

当我想反序列化 xml 时,我调用

XMLDeserializerFacade.DeserializeXml("file.xml")

我的问题是我lock也应该在OnElementDeserializedCallback回调中使用?

谢谢

4

1 回答 1

4

这在很大程度上取决于具体的实现。如果调用它的代码与 main lock/位于同一线程上DeserializeXml,并且它使用同步版本(OnElementDeserializedCallback(...)OnElementDeserializedCallback.Invoke(...))-那么它将已经在现有锁内,因为锁本质上是与线程绑定的。

如果实现使用异步实现(BeginInvoke,TaskThreadPool),则不:它不会在锁内。

如果不确定,你可以在两个地方都加锁(因为锁是可重入的,如果你最终从同一个线程两次嵌套锁定也没关系);但是,如果结果证明它异步的,但它还会尝试加入回回调(Delegate.EndInvoke,Task.Wait等),那么它可能会完全死锁。

于 2012-11-08T10:35:03.360 回答