gpt4 book ai didi

c# - FileSystemWatcher - 从 ObservableCollection 添加和删除,C#

转载 作者:太空宇宙 更新时间:2023-11-03 23:22:55 25 4
gpt4 key购买 nike

首先,我的代码:

private void OnChangedActive(object source, FileSystemEventArgs e)
{
try
{
switch (e.ChangeType)
{
case WatcherChangeTypes.Created:
if (File.Exists(e.FullPath))
{
MachineOrder machineOrderAdded;

machineOrderAdded = viewModel.MachineOrdersActive.FirstOrDefault(x => x.Filename == e.Name);
if (machineOrderAdded != null)
this.Dispatcher.BeginInvoke(new Action(() => viewModel.MachineOrdersActive.Remove(machineOrderAdded)));

machineOrderAdded = viewModel.MachineOrdersProductionpool.FirstOrDefault(x => x.Filename == e.Name);
if (machineOrderAdded != null)
this.Dispatcher.BeginInvoke(new Action(() => viewModel.MachineOrdersProductionpool.Remove(machineOrderAdded)));

machineOrderAdded = viewModel.MachineOrdersInProduction.FirstOrDefault(x => x.Filename == e.Name);
if (machineOrderAdded != null)
this.Dispatcher.BeginInvoke(new Action(() => viewModel.MachineOrdersInProduction.Remove(machineOrderAdded)));


this.Dispatcher.BeginInvoke(new Action(() => viewModel.MachineOrdersActive.Add(mainController.generateMachineOrder(e.FullPath))));
}

break;
case WatcherChangeTypes.Deleted:

MachineOrder machineOrder;
String message = "";

//ÜBERPRÜFEN, OB SIE IM AKTIVORDNER IST
machineOrder = viewModel.MachineOrdersActive.FirstOrDefault(x => x.Filename == e.Name);

if (machineOrder != null)
{
this.Dispatcher.BeginInvoke(new Action(() => viewModel.MachineOrdersActive.Remove(machineOrder)));
message = String.Format("Die Datei {0} existiert nicht mehr. Der dazugehörige Auftrag wurde von den aktiven Aufträgen entfernt.", machineOrder.Filename);
this.Dispatcher.BeginInvoke(new Action(() => setStatus(message, Level.INFO)));
Logger.getInstance().writeLogEntry(Logger.LogLevel.INFO, message, null);
break;
}


//ÜBERPRÜFEN, OB SIE IM FERTIGUNGSPOOL IST
machineOrder = viewModel.MachineOrdersProductionpool.FirstOrDefault(x => x.Filename == e.Name);

if (machineOrder != null)
{
this.Dispatcher.BeginInvoke(new Action(() => viewModel.MachineOrdersProductionpool.Remove(machineOrder)));
message = String.Format("Die Datei {0} existiert nicht mehr. Der dazugehörige Auftrag wurde aus dem Fertigungspool entfernt.", machineOrder.Filename);
this.Dispatcher.BeginInvoke(new Action(() => setStatus(message, Level.INFO)));
Logger.getInstance().writeLogEntry(Logger.LogLevel.INFO, message, null);
break;
}


//ÜBERPRÜFEN, OB SIE IM FERTIGUNGSSPEICHER IST
machineOrder = viewModel.MachineOrdersInProduction.FirstOrDefault(x => x.Filename == e.Name);

if (machineOrder != null)
{
message = String.Format("Die Datei {0} existiert nicht mehr. Der dazugehörige Auftrag wurde nicht entfernt, da er sich bereits in Produktion befindet", machineOrder.Filename);
this.Dispatcher.BeginInvoke(new Action(() => setStatus(message, Level.INFO)));
Logger.getInstance().writeLogEntry(Logger.LogLevel.INFO, message, null);
break;
}


//NACHRICHT AUSGEBEN
if (String.IsNullOrEmpty(message))
{
message = String.Format("Die Datei {0} existiert nicht mehr. Der dazugehörige Auftrag wurde nicht gefunden.", machineOrder.Filename);
this.Dispatcher.BeginInvoke(new Action(() => setStatus(message, Level.INFO)));
Logger.getInstance().writeLogEntry(Logger.LogLevel.INFO, message, null);
}




break;
default:
break;
}
}
catch (Exception ex)
{
this.Dispatcher.BeginInvoke(new Action(() => setStatus(ex.Message, Level.ERROR)));
Logger.getInstance().writeLogEntry(Logger.LogLevel.INFO, ex.Message, ex.StackTrace);
}

}

这里我有 3 个基于三个不同可观察集合的数据网格。如果一个文件夹添加了很多文件(或者删除了很多文件),时不时会漏掉一个文件,报错:

Collection was modified; enumeration operation may not execute

有什么线索可以找到丢失的文件吗?

最佳答案

你有明显的竞争条件:

machineOrderAdded = viewModel.MachineOrdersActive.FirstOrDefault(x => x.Filename == e.Name);
if (machineOrderAdded != null)
this.Dispatcher.BeginInvoke(new Action(() => viewModel.MachineOrdersActive.Remove(machineOrderAdded)));

要修复它,请将所有内容移入 Invoke:

Dispatcher.InvokeAsync(() =>
{
var machineOrderAdded = viewModel.MachineOrdersActive.FirstOrDefault(x => x.Filename == e.Name);
if(machineOrderAdded != null)
viewModel.MachineOrdersActive.Remove(machineOrderAdded);
});

以此类推,在所有情况下,避免从 UI 线程以外的任何其他地方访问集合。

你也可以尝试同步访问集合,e.q.使用 lock 或使用线程安全的集合。这will not work使用 ObservableCollection

根据@HansPassant 的评论,您可以简单地将 FileSystemWatcher 事件直接调用到 UI 线程中,并在那里执行所有 switch/case

// using reinvoke pattern, you can invoke another method to avoid "double-checking"
void OnChangedActive(object source, FileSystemEventArgs e)
{
if (!Dispatcher.CheckAccess())
Dispatcher.InvokeAsync(() => OnChangedActive(sender, e)); // sorry for InvokeAsync :)
else
{
... // your code goes here without need to use invoke
}
}

关于c# - FileSystemWatcher - 从 ObservableCollection 添加和删除,C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34744518/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com