views:

154

answers:

3

Project is C#.

So I have a bunch of multithreaded code that is designed to be run as a library. It's in a seperate project from the UI.

My library has a central object that needs to be created before anything that would fire off events is created.

Is it possible for this master object to be passed in some objects so that my events can figure out when they would need to be invoked to get back to the main UI thread?

I'd really like to keep the UI from have to do a bunch of invoking since his event handlers are almost always going to be called from some random background thread.

A: 

Using a timer, or responding to an event, the UI thread (or a databound object on the thread) could poll a "status" object and limit the amount of work the UI must do.

Doug L.
+8  A: 

From what you're describing, your best option might be to make all of your objects take a SynchronizationContext as a argument in their constructor.

If you do that, when you need to raise an event, you can use SyncrhonizationContext.Post to "invoke" the event on the UI thread.

This way, your library will be UI-agnostic (could work in Windows Forms or WPF), and you can raise events on the UI thread as needed.

The user of your library would just create your object using SynchronizationContext.Current (which gives you a valid context in Windows Forms and WPF applications, without pulling in a reference to either).

Reed Copsey
Yeah this is it, the way to form the Post call is a bit tricky, but this is going to be perfect.
Joel Barsotti
I'll probably spind this off on to a seperate thread, but I saw an example where the method that calls the event compares the current SyncrhonizationContext with the one I store from the UI.In WPF, these don't ever seem to compare as true. So I get infinite recursion and the UI locks up. Do you know a good UI agnostic check to see if I need to do the Post? Should I just always call the post and just post the event directly?
Joel Barsotti
Well, you can always post/send, and not worry about it. It will have a (slight) overhead if its unnecessary, but it's usually not an issue. If you're actually on a background thread, SynchronizationContext.Current will be null (since "normal" threads don't have a context attached).
Reed Copsey
right, I've noticed that.But after the SyncrhonizationContext.Post, on Windows Forms the SyncrhonizationContext.Current will evaluate on an == operator to the value I'm storing in my singleton, in WPF it won't.Am I just using the wrong value to check, or if i just check SyncrhonizationContext.Current for a null condition could that lighter check come back to bite me?Also if the post is fairly lightweight, then maybe just always posting and loosing the recursion is the right answer.Thank you so much for your help.
Joel Barsotti
A: 

Have you looked at the Facade, Proxy, Factory and Singleton patterns?

If you implement your core object as a Singleton, and provide proxy and factory methods to produce and deliver these to callers of your library this becomes fairly straight-forward. The Facade pattern can make this easier by abstracting away most of the internals of what is going on in the backend.

Combining Factory and Singleton, and ensuring that all classes you want exposed have constructors requiring your main object is a good way to enforce this design. I dont know the main requirements/design of your library, so I am not sure if this would work for you or not.

GrayWizardx
Yeah it's actually set up something like that.I think combined with the SynchronizationContext I should have what I need to do what I want.
Joel Barsotti