私の現在のプロジェクトでは、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);
};
}
}
}