I have a PropertyGrid in my application that is used for editing arbitrary objects. I need to be able to run an arbitrary subroutine on another thread that also looks at these objects (search functionality, if you’re curious). The obvious issue is that a user could be editing one of these objects at the same time my search thread is reading it, which would be preferable to avoid (although it probably won’t result in anything critical since my search thread is just reading, not writing).
Calling lock(obj) is easy enough from my search thread, but after looking through the documentation and a brief skim through the PropertyDescriptorGridEntry code in Reflector, I cannot seem to find an analogous spot to use a System.Threading.Monitor.Enter()/Exit() call on the object in question on the PropertyGrid. I was hoping there would be BeginEdit and EndEdit events which would make this simple enough, but I can’t seem to find any such thing. I’d rather not lock the entire object while it’s on display in the PropertyGrid as that would obviously block my search thread until another object was selected.
I’m a bit new to the threading model of Windows Forms, so I’m hoping there’s some obvious answer I’ve just overlooked. Any help?
Edit: Synchronously cloning my objects before running the search asynchronously will likely be inefficient enough that I might as well run the search itself synchronously – the point of running asynchronously is of course to allow my users to continue to work while the search is executing. The search needs to scale well, as the data set I am going through will eventually end up being arbitrarily large, which makes synchronous cloning look like it will cause the usability problem I am trying to avoid.
I think you are going to have to do quite a bit of work for this.
First, you would have to create an implementation of ICustomTypeDescriptor which would base its implementation on whatever TypeDescriptor you would normally get for that type.
Then, in the implementations of the methods which expose the descriptors of the members you want to lock on, you would provide subclasses which derive from those descriptors and override the appropriate methods to wrap a lock around.
So for a property, you would implement GetProperties to return your specific subclasses of PropertyDescriptor. These subclasses would override the GetValue and SetValue methods (and others) and use a lock when accessing those variables.
It should be mentioned that locking like this in the UI thread is probably a bad idea, since you don’t want to arbitrarily block operations on that thread. It might be better to just create a clone of the object and then have a method which updates the store of objects when you are done.