C# / WPF - CurrentDispatcher 和 DispatchTimer - 非常罕见的并发修改异常

发布于 2024-11-16 18:04:32 字数 1385 浏览 2 评论 0原文

我有一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

横笛休吹塞上声 2024-11-23 18:04:32

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 the Dispatcher for "the thread currently executing", not the UI thread's Dispatcher. You most likely need to change this to something like Application.Current.Dispatcher.BeginInvoke (the Dispatcher associated with the current Application), or some UIElement's Dispatcher.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文