C# / WPF - CurrentDispatcher 和 DispatchTimer - 非常罕见的并发修改异常
我有一个 WPF GUI,可能每天都会抛出一次特定错误。
“Collection was modified after the enumerator was Instantiated"
它所指的特定集合是时间戳字典。 'dict' 是一个私有成员变量。
dict = new Dictionary<string, List<DateTime>>();
有两个地方引用了 Collection,都应该仅在调度线程上调用。第一个位置用于添加到字典中,当 ViewModel 上的特定 DependencyProperty 更改时调用,
void CalledFromDispatch(Item i)
{
dict[i.Category].Add(DateTime.UtcNow);
}
第二个位置是我从字典中读取的位置。 Outstanding 是一个布尔依赖属性。
void PeriodicUpdate()
{
HasOutstanding = dict["New"].Any();
}
对 HasOutstanding
的赋值是抛出异常的地方,我知道我可以使用 Count > 0
来解决问题,但我担心异常是可能的。
实际上,第一段代码的调用方式如下:
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.DataBind, () => CalledFromDispatch(i));
第二个是这样安排的;
DispatcherTimer DispatcherTimer = new DispatcherTimer(DispatcherPriority.DataBind)
DispatcherTimer.Interval = TimeSpan.FromSeconds(1);
DispatcherTimer.Start();
...
DispatcherTimer.Tick += (s, e) => PeriodicUpdate();
所以我的问题归结为:
- DispatchTimer 是否与 CurrentDispatcher 使用相同的线程?
- 如果是这样,调度程序是否有可能在执行过程中切换计划的操作?
不然我都不知道怎么会出现这样的情况。
我真的很想了解有关 DispatchTimer 如何与 CurrentDispatcher 交互的更多信息。如果有人拥有可能有助于澄清情况的资源,那么我将非常感谢该链接。
I have a WPF GUI that throws a specific error perhaps once a day.
“Collection was modified after the enumerator was Instantiated"
The specific collection to which it's referring is a Dictionary of TimeStamps. 'dict' is a private member variable.
dict = new Dictionary<string, List<DateTime>>();
There are two places where the Collection is referenced, both should only be called on the dispatch thread. The first location is for adding to the dictionary and is called when a specific DependencyProperty on a ViewModel changes,
void CalledFromDispatch(Item i)
{
dict[i.Category].Add(DateTime.UtcNow);
}
The second place is where I read from the Dictionary. Outstanding is a bool dependency property.
void PeriodicUpdate()
{
HasOutstanding = dict["New"].Any();
}
The Assignment to HasOutstanding
is where the exception is thrown, I know I could use Count > 0
to solve the problem but it worries me that the exception is possible.
The first piece of code is called, in effect, like this;
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.DataBind, () => CalledFromDispatch(i));
The second is scheduled like this;
DispatcherTimer DispatcherTimer = new DispatcherTimer(DispatcherPriority.DataBind)
DispatcherTimer.Interval = TimeSpan.FromSeconds(1);
DispatcherTimer.Start();
...
DispatcherTimer.Tick += (s, e) => PeriodicUpdate();
So my questions boil down to;
- Does the DispatchTimer use the same thread as the CurrentDispatcher?
- If so, is it possible that the Dispatcher might switch out a scheduled operation mid execution?
Otherwise I don't know how this occurs.
I'd really love to learn more about how the DispatchTimer interacts with the CurrentDispatcher. If anyone has a resource which might help clarify the situation then I'd greatly appreciate the link.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果这两个都是在 UI 线程上调用/设置的,那就应该没问题。
我怀疑您错误地使用了
BeginInvoke
。Dispatcher.CurrentDispatcher
< /a> 是“当前正在执行的线程”的Dispatcher
,不是UI 线程的Dispatcher。您很可能需要将其更改为诸如Application.Current.Dispatcher.BeginInvoke
(与当前应用程序关联的调度程序)或某些 UIElement 的调度程序。Provided that both of these were called/setup on the UI thread, it should be fine.
My suspicion is that you're using
BeginInvoke
incorrectly.Dispatcher.CurrentDispatcher
is theDispatcher
for "the thread currently executing", not the UI thread's Dispatcher. You most likely need to change this to something likeApplication.Current.Dispatcher.BeginInvoke
(the Dispatcher associated with the current Application), or some UIElement's Dispatcher.