根据计时器引发更新集合'集合已修改;枚举操作可能无法执行." [英] Update collection based on timer throws 'Collection was modified; enumeration operation may not execute.'
问题描述
我正在使用Reactive Extensions和ReactiveUI定期更新 Process
对象的集合.
I'm using Reactive Extensions and ReactiveUI to update a collection of Process
objects periodically.
选中复选框后,将填充绑定到DataGrid的属性Processes,并设置计时器以每200ms更新所有进程.退出的进程将被删除.
When a checkbox is checked the property Processes, which is bound to a DataGrid, is filled and a timer is set to update every 200ms all processes. Processes that have exited are removed.
集合已修改;枚举操作可能无法执行.
有时在进行foreach时会引发异常.我不明白,因为我没有在迭代时删除或向集合中添加对象(只需设置 ProcessModel
的属性)
The Collection was modified; enumeration operation may not execute.
exception is sometimes thrown when doing a foreach. I don't understand, because I am not removing or adding objects to the collection when iterating (just setting a property of the ProcessModel
)
计时器还会等到一切完成后再触发吗?
Also does the timer wait until everything is completed before firing again?
ViewModel
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
}
}
推荐答案
最好发布一个最小,完整,可验证的示例为您提供帮助.无法按书面要求进行调试或测试.
It is best to post a minimal, complete, verifiable example to help you. This isn't possible to debug or test as written.
作为猜测,我假设您有某种处理程序,该处理程序是由 OnPropertyChanged(nameof(ProcessObject));
调用触发的.此处理程序可能会从可枚举中删除并可能重新添加了该对象.要进行测试,您可以分离处理程序,或删除调用,看看是否仍然发生异常.
As a guess, I would assume you have some sort of handler which is being triggered by the OnPropertyChanged(nameof(ProcessObject));
call. This handler probably removes and possibly re-adds the object from the enumerable. To test, you can detach the handler, or remove the call and see if the exception still occurs.
这篇关于根据计时器引发更新集合'集合已修改;枚举操作可能无法执行."的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!