.Net PropertyGrid线程安全性

.Net PropertyGrid线程安全性,.net,multithreading,propertygrid,.net,Multithreading,Propertygrid,我的应用程序中有一个PropertyGrid,用于编辑任意对象。我需要能够在另一个线程上运行任意子例程,该线程也可以查看这些对象(如果您好奇,可以使用搜索功能)。显而易见的问题是,用户可能会在我的搜索线程读取这些对象的同时编辑其中一个对象,这是最好避免的(尽管这可能不会导致任何重要的结果,因为我的搜索线程只是读取,而不是写入) 从我的搜索线程调用lock(obj)非常简单,但是在查看了文档并简要浏览了Reflector中的PropertyDescriptorGridEntry代码之后,我似乎找不

我的应用程序中有一个
PropertyGrid
,用于编辑任意对象。我需要能够在另一个线程上运行任意子例程,该线程也可以查看这些对象(如果您好奇,可以使用搜索功能)。显而易见的问题是,用户可能会在我的搜索线程读取这些对象的同时编辑其中一个对象,这是最好避免的(尽管这可能不会导致任何重要的结果,因为我的搜索线程只是读取,而不是写入)

从我的搜索线程调用
lock(obj)
非常简单,但是在查看了文档并简要浏览了Reflector中的PropertyDescriptorGridEntry代码之后,我似乎找不到类似的地方来使用
System.Threading.Monitor.Enter()/Exit()
调用PropertyGrid上的相关对象。我希望会有BeginEdit和EndEdit事件,这会使事情变得足够简单,但我似乎找不到任何这样的事情。我不希望在PropertyGrid中显示整个对象时锁定它,因为这显然会阻止我的搜索线程,直到选择了另一个对象

我对Windows窗体的线程模型有点陌生,所以我希望有一些我刚刚忽略的显而易见的答案。有什么帮助吗


编辑:在异步运行搜索之前同步克隆我的对象可能效率很低,我不妨同步运行搜索本身-异步运行的目的当然是让我的用户在搜索执行时继续工作。搜索需要很好地扩展,因为我正在浏览的数据集最终会变得任意大,这使得同步克隆看起来像是会导致我试图避免的可用性问题。

这确实不是线程安全的。您可以将一些搜索代码封送到UI线程,但这会降低速度,并且可能会破坏线程的作用


搜索需要多快?你能对付克隆人吗?etc

能否在显示数据之前克隆数据,并让搜索线程处理克隆?如果希望搜索线程“查看”更改,可以响应
PropertyGrid
上的事件,并可能以某种方式对克隆进行受控更改。(不过,只使用“过时”数据可能更容易。)


我知道克隆数据听起来效率非常低,但当每个线程处理完全独立的数据(或者所有线程都只读取数据)时,线程处理肯定会更简单。

我认为您必须为此做大量工作

首先,您必须创建ICustomTypeDescriptor的实现,该实现将基于您通常为该类型获得的任何TypeDescriptor

然后,在公开要锁定的成员的描述符的方法的实现中,您将提供从这些描述符派生的子类,并重写适当的方法来封装锁

因此,对于属性,您将实现GetProperties以返回PropertyDescriptor的特定子类。这些子类将重写GetValue和SetValue方法(以及其他方法),并在访问这些变量时使用锁


应该提到的是,在UI线程中像这样锁定可能是个坏主意,因为您不想任意阻止该线程上的操作。最好只是创建对象的克隆,然后使用一种方法在完成后更新对象的存储。

我可能错了,但在我看来,你来错了

您需要解决两个截然不同的问题

首先,确保仅在UI线程上访问PropertyGrid。如果它的任何方法(包括属性getter/setter)是从其他线程访问的,您将以神秘的方式遭受痛苦。当然,例外情况是
invokererequired()
Invoke

其次,确保你的搜索线程可以正常运行

要解决第一个问题,请确保除UI线程外,对象从未被修改,或者使所有事件触发器都具有线程意识,以便仅在UI线程上触发对象事件(如PropertyChanged)


第二个问题更容易——只要搜索线程只读取核心对象,一切都应该正常工作。是的,您的搜索线程可能会无意中看到一些部分更新的数据,但这真的是一个问题吗

最后的几点想法

  • 不要执行搜索来迭代PropertyGrid本身;提前获取一个对象列表(它们不需要是克隆对象),然后进行处理

  • 您是否考虑过使用空闲处理进行搜索?
    应用程序
    对象在应用程序每次用完要处理的消息时都会触发一个事件-您可以挂接到该事件,并在每次触发事件时执行一个搜索步骤。有点糟糕的人线程,但没有互斥锁/锁/语义电话的麻烦。我过去用过这个,效果很好

更新:如果我没记错的话,PropertyGrid尊重接口,在您开始修改行时以及移动到其他行时调用。您可以利用它来防止搜索线程看到不完整的更改

更新2:接下来,我发现了您已经知道的一点——PropertyGrid不尊重IEditableObject接口

我还有另一个建议——尽管这可能比你想投资的工作要多

大约在.NET2.0中引入System.Transactions命名空间时,我看到了一篇关于使用环境事务为obj提供线程隔离的文章