【发布时间】:2023-04-02 00:51:01
【问题描述】:
我正在尝试找出将锁定应用于以下类的正确方法。简而言之,该对象是一个单例对象,当创建时,它会从给定目录中的 xml 文件构建可变数量的菜单。现在,只允许读取,因此不会发生锁定(MSDN 状态读取是字典中的线程安全的)。但是,我还连接了一个文件系统观察程序,以便在发生更改时重新构建菜单。有两个字典发生读取,所以我需要一种方法来处理这个问题。我可以使用 Lock(this),但有更好的方法吗?所以,我唯一想冻结读取的时间是更新发生时(查看 ctor)。
这是一个视觉类:
public class XmlMenuProvider : IMenuProvider {
private readonly INavigationService navigation;
private readonly Dictionary<string, IEnumerable<MenuItem>> menus;
private readonly Dictionary<string, Dictionary<string, MenuItem>> menusLookup;
private readonly FileSystemWatcher monitor;
public XmlMenuProvider(string folderPath, INavigationService navigation)
{
this.navigation = navigation;
this.menusLookup = new Dictionary<string, Dictionary<string, MenuItem>>();
this.menus = LoadFromSourceDirectory(folderPath);
this.monitor.Changed += (o, e) => {
// TODO - Add Locking
};
}
public IEnumerable<MenuItem> GetMenuItems(string name) {
return menus[name];
}
public MenuItem FindItemByName(string menu, string name) {
return menusLookup[menu][name];
}
private Dictionary<string, IEnumerable<MenuItem>> LoadFromSourceDirectory(string folderPath) {
var menus = new Dictionary<string, IEnumerable<MenuItem>>();
foreach (var file in Directory.GetFiles(folderPath, "*.xml")) {
var root = XDocument.Load(file).Elements().First();
var name = root.Attribute("name").Value;
var lookup = new Dictionary<string, MenuItem>();
menusLookup.Add(name, lookup);
menus.Add(name, BuildMenuHiearchyFromElement(root, lookup, null));
}
return menus;
}
private IEnumerable<MenuItem> BuildMenuHiearchyFromElement(XElement element, Dictionary<string, MenuItem> lookup, MenuItem parent) {
return element.Elements("Item")
.Select(e => {
var mi = CreateMenuItemFromElement(e, lookup, parent);
lookup.Add(mi.Name, mi);
return mi;
}
).ToList();
}
private MenuItem CreateMenuItemFromElement(XElement element, Dictionary<string, MenuItem> lookup, MenuItem parent) {
var name = element.Attribute("Name").Value;
var display = element.Attribute("DisplayName").Value;
var isClickable = true;
var roles = element.Attribute("Roles").Value.Split(',');
if (roles.Length == 1 && roles.First() == string.Empty) {
roles = new string[] { };
}
var attrClick = element.Attribute("IsClickable");
if (attrClick != null) {
isClickable = bool.Parse(attrClick.Value);
}
var navigateUrl = string.Empty;
if (isClickable) {
navigateUrl = navigation.FetchDestination(name);
}
return new MenuItem(name, display, navigateUrl, isClickable, roles, x => BuildMenuHiearchyFromElement(element, lookup, x), parent);
}
}
谢谢。
【问题讨论】:
标签: c# multithreading concurrency