我正在使用Reactive Extensions和ReactiveUI定期更新Process
个对象的集合。
当选中复选框时,将填充绑定到DataGrid的属性Processes,并设置一个计时器以每200ms更新所有进程。退出的进程将被删除。
执行foreach时有时会抛出Collection was modified; enumeration operation may not execute.
异常。我不明白,因为我在迭代时没有删除或添加对象(仅设置ProcessModel
的属性)
定时器是否等到一切都完成后才再次开火?
视图模型
private ReactiveList<IProcessModel> _processes = new ReactiveList<IProcessModel>() { ChangeTrackingEnabled = true };
public ReactiveList<IProcessModel> Processes { get { return _processes; } }
IDisposable timer;
private void DoShowProcesses(bool checkboxChecked)
{
Processes.Clear();
if (checkboxChecked)
{
//checkbox checked
lock (Processes)
Processes.AddRange(_monitorService.GetProcesses());
timer = Observable.Timer(TimeSpan.FromMilliseconds(200.0))
.Select(x =>
{
lock (Processes)
{
foreach (var process in Processes) //throws the 'Collection was modified; enumeration operation may not execute.'
process.UpdateMemory();
return Processes.Where(p => p.ProcessObject.HasExited).ToList();
}
}).
ObserveOnDispatcher()
.Subscribe(processesExited =>
{
if (processesExited.Count() > 0)
{
lock (Processes)
Processes.RemoveAll(processesExited); //remove all processes that have exited
}
});
}
else
{
if (timer != null)
timer.Dispose();
}
}
中processModel
public class ProcessModel : ProcessModelBase, IProcessModel
{
public ProcessModel(Process process)
{
ProcessObject = process;
}
public void UpdateMemory()
{
try
{
if (!ProcessObject.HasExited)
{
long mem = ProcessObject.PagedMemorySize64;
ProcessObject.Refresh();
if (mem != ProcessObject.PagedMemorySize64)
OnPropertyChanged(nameof(ProcessObject));
}
}
catch (Exception)
{
//log it
}
}
答案 0 :(得分:-1)
最好发布minimal, complete, verifiable example来帮助您。这不可能像编写的那样进行调试或测试。
作为一种猜测,我认为你有一些由OnPropertyChanged(nameof(ProcessObject));
调用触发的处理程序。此处理程序可能会从可枚举中删除并可能重新添加该对象。要进行测试,您可以分离处理程序,或者删除调用并查看是否仍然发生异常。