C#:锁定语句中的回调函数是否也被锁定?

时间:2012-11-08 10:20:37

标签: c# asp.net caching thread-safety locking

我有一个函数可以反序列化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吗?

谢谢

1 个答案:

答案 0 :(得分:4)

这在很大程度上取决于具体实施。如果调用的代码与主lock / DeserializeXml在同一个线程上,并且它使用同步版本(OnElementDeserializedCallback(...)或{{1} }) - 然后它将已经存在于现有锁内,因为锁基本上与线程相关联。

如果实现使用异步实现(OnElementDeserializedCallback.Invoke(...)BeginInvokeTask等),那么否:它将在锁内。

如果不确定,你可以锁定两个地方(因为锁是可重入的,如果你最终从同一个线程中嵌套锁定两次并不重要);但是,如果结果是异步,但它也会尝试加入回调(ThreadPoolDelegate.EndInvoke等)然后它可能完全陷入僵局。