【发布时间】:2011-04-03 19:00:14
【问题描述】:
一直在对多线程 C# 事件处理进行一些简短的研究,因为我怀疑事件处理程序只会在调用事件的任何线程上被调用,事实证明这是真的。
现在这让我觉得这是一个非常糟糕的主意,因为订阅对象上的事件的代码可能根本不是设计为多线程的,并且该对象的实现(应该是一个黑盒子,不是吗? ),如果幕后的多线程(如我的情况)会导致订阅者代码在多个线程上执行,从而导致各种奇怪的问题。
所以我的问题是,是否可以将事件推送回最初订阅它的线程,从而避免订阅者级别的任何意外并发?或者更抽象地说,我是否可以在某个时间点记录当前线程,并在稍后的某个时间点将事件处理程序调用(或任意一段代码)推送到该线程上?
关键是:我在不引用 WinForms 或 WPF 的 DLL 中执行此操作。我知道这些框架中存在允许这样做的构造(我自己也使用过它们),但我想这样做而不必引用这些库。
一点背景:
我的设计使用后台线程来处理一个对象,这可能会导致其属性发生变化。我使用 INotifyPropertyChanged 向观察者表明对这些属性的更改。我在库外部使用 WPF 在接口中显示这些对象,因此 INotifyPropertyChanged 很有用,因为它告诉 WPF 在正在显示的对象上的属性发生更改时更新屏幕。
我假设 WPF 在内部处理多线程更改通知,所以如果我只坚持 WPF,可能不会有问题。但是,我希望任何人都能够订阅更改事件,而不必担心它们会在后台线程上被调用。
【问题讨论】:
-
您遇到了更大的问题,您正在更新工作线程中的属性,这些属性也可能(可能会)在 UI 线程中使用。您还需要确保 UI 线程以线程安全的方式使用它们。
-
在后台线程中设置的属性只会被其他线程读取,所以这应该不是问题。
-
呃,如果 UI 线程不读取这些属性,那么生成事件的意义何在? “仅由其他线程读取”是问题,您不能在没有同步的情况下在一个线程上写入并在其他线程上读取。
-
“其他线程”是指除了写作线程之外的其他线程——即包括 UI 线程。我认为在其他线程上阅读没有问题,至少没有考虑到设计的其余部分。主要从 INotifyPropertyChanged 的角度来考虑它——我们只需要在属性更改时通知观察者,以便它可以更新内容。不完全同步也没关系,只要每次更改后都有一个 PropertyChanged 事件。
标签: c# .net multithreading events