【发布时间】:2016-01-12 13:06:21
【问题描述】:
首先,我的代码:
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 个基于三个不同可观察集合的 dataGrid。 如果一个文件夹添加了很多文件(或删除了很多文件),它会时不时丢失一个文件并出现错误:
Collection was modified; enumeration operation may not execute
任何线索如何捕捉丢失的文件?
【问题讨论】:
-
此消息表示您正在迭代期间修改迭代器集合。也许您必须创建收藏的副本,并将添加的文件复制到新收藏中(与已删除文件相同的过程)。
-
哪一行出现异常?
-
stacktrace 在这一行说:machineOrderAdded = viewModel.MachineOrdersActive.FirstOrDefault(x => x.Filename == e.Name);
-
这是因为您有机会在 UI 线程删除某些内容、修改集合并且您遇到异常的确切时刻枚举集合(在 linq 查询中)。是设计问题。在 MVVM 中,只有
ViewModel可以更新ObservableCollection,模型(处理FileSystemWatcher)应该使用自己的List操作或简单地向 ViewModel 发送通知。在您的情况下,简单的解决方法是永远不要枚举Invoke委托之外的集合。 -
线程正在吃你的午餐。不要在此代码中添加 BeginInvoke 调用,只需使用 one 并让目标方法执行 switch 语句。
标签: c# wpf filesystemwatcher