我有一个反序列化 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")
我的问题是我是否也应该在 OnElementDeserializedCallback
回调中使用 lock
?
谢谢
最佳答案
这在很大程度上取决于具体的实现。如果调用它的代码与主 lock
/DeserializeXml
在同一线程上,并且它使用同步版本(OnElementDeserializedCallback (...)
或 OnElementDeserializedCallback.Invoke(...)
) - 那么它将已经在现有的锁中,因为锁基本上与线程相关联。
如果实现使用异步实现(BeginInvoke
、Task
、ThreadPool
等),则否:它不会在锁内。
如果不确定,您可以在两个地方都加锁(因为锁是可重入的,所以即使您最终从同一个线程获得两次嵌套加锁也没关系);然而,如果事实证明它是 异步的,但它也会尝试返回回调(Delegate.EndInvoke
, Task.Wait
等)然后它可能会完全死锁。
关于C#:lock 语句中的回调函数是否也被锁定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13287053/