在我目前的项目中,我正在使用Boo / Rhino DSL(顺便说一句,这是一件多么棒的事情)。
在挖掘代码时,我遇到了以下代码:
engine.Cache.WriteLock( () =>
{
engine.Storage.NotifyOnChange(urls, delegate(string invalidatedUrl)
{
engine.Cache.Remove(invalidatedUrl);
if (!standAloneCompilation.Contains(invalidatedUrl))
standAloneCompilation.Add(invalidatedUrl);
});
});
这里的意图很清楚:engine.Cache
当一个 url 被从中删除时,必须保护它免受竞争条件的影响。我在这里看到的问题是,真正受到保护的是调用Storage.NotifyOnChange
- 而不是Cache.Remove
.
所做NotifyOnChange
的只是获取提供的委托并将其作为事件处理程序附加到它创建的“FileWatcher”。因此,这里不是保护Cache.Remove
写锁,而是保护创建 FileWatcher,而不是Cache.Remove
保护未受保护的。
我对 Boo 和 Rhino 都非常尊重,这让我想知道——这里有什么遗漏吗?或者写锁应该真的在委托内部移动?
如果您想知道,这里是 NotifyOnChange 代码:
public virtual void NotifyOnChange(IEnumerable<string> urls, Action<string> action)
{
lock (pathToFileWatchers)
{
string[] commonPaths = GatherCommonPaths(urls);
foreach (string path in commonPaths)
{
FileSystemWatcher watcher;
if(pathToFileWatchers.TryGetValue(path, out watcher)==false)
{
pathToFileWatchers[path] = watcher = new FileSystemWatcher(path, FileNameFormat);
watcher.EnableRaisingEvents = true;
}
watcher.Changed += delegate(object sender, FileSystemEventArgs e)
{
action(e.FullPath);
};
}
}
}