views:

240

answers:

4

I am reading this blog: Use Threads Correctly, and I am wondering:

How to implement a message (Note: I don't mean Windows Message here) pump in a non-UI thread?

What I want is that the message can be an object or a command, say an Action<T>/Func<T>, etc. Do I have to use separate queue for different type of message? Say one queue for object, one queue for Action<T>/Func<T>?

Given that the type of messages vary, how to implement it?

EDIT:

What I want to complete is a producer/consumer model, producer/consumer share queue for communication, the queue can not only contain object for the consumer to consume, but also some 'command' can be passed to the consumer for execution.

+1  A: 

Well, you'll need Thread.SetApartmentState() to switch the Thread to STA before you start it, then call Application.Run() in the thread function to start the message loop.

This has nothing to do with the Action and Func delegates though. The message queue is an internal Windows structure that stores mouse and keyboard messages. It is not suitable to store your own objects. Not sure where you want to go with this.


A regular System.Collections.Generic.Queue<> object can store any kind of object, including an object of a class that represents a "command". Make it thread-safe with a ReaderWriterLockSlim.

Hans Passant
sorry, I am asking about Non-ui thread.
Benny
There's no point in starting a message loop in a thread that doesn't display any UI or uses classes that require a message pump (like WebBrowser). Keep this thread moving by explaining why you think you need a message loop.
Hans Passant
@nobugz, the message i am talking about is not windows message.
Benny
If it is not a Windows message then you won't have a use for a message loop. Check this thread: http://stackoverflow.com/questions/2222365/what-is-a-message-pump
Hans Passant
thanks, I've updated my problem to be more clear.
Benny
@Benny: answer updated, below the line.
Hans Passant
+2  A: 
Aaronaught
thanks, I've updated my problem to be more clear.
Benny
@Benny: I don't find that much more clear. It is **highly** unusual to be queuing delegates this way, and would again state that whatever you are trying to do sounds better handled via the `ThreadPool`, unless you really need ordering of these "commands."
Aaronaught
+1  A: 

I am a little confused on what your end goal is but it seems like you are looking for two things.

First in the case where you want to pass objects around (presumably you are thinking of a message queue for the purposes of cross thread communication?) it sounds like you want a pub/sub type implementation? That is pretty well documented and there are many examples out there in C#

For the second case where you want to pass a delegate as the payload of the message I am guessing you are trying to implement some sort of two way communication between publisher and subscriber? Something like a callback?

This is where I am getting confused. What exactly is the question / problem here? You could implement a single message queue that understands how to handle different message payload types. Something like BroadcastMessage where T is object for your first case and delegate (Func / action) for the second case.

I have a codeplex project that is a simple implementation of a messaging queue that I use for specific purposes within MVC / MVVM applications. Not sure this is what you are looking for but it might help you clarify your question further?

http://courier.codeplex.com/

Foovanadil
thanks, i've updated my problem to be more clear.
Benny
+1  A: 

Made this a seperate answer for code formatting

Ok so after reading your update I think you want what I describe in the "second case" you simply want

Broadcast<T>("Foo") 

where T is a delegate.

Then your consumer will do

Subscribe<T>("Foo",HandlerMethod)

So a producer consumer scenario would look like this

internal static class MessagePump
    {

        public static void Subscribe<T>(String foo, Action<String> handlerMethod)
        {
            throw new NotImplementedException();
        }

        public static void BroadcastMessage<T>(String foo, Action<String> someAction)
        {
            throw new NotImplementedException();
        }
    }

    public class Producer
    {
        void SendMessage()
        {
            MessagePump.BroadcastMessage<Action<String>>("Foo", SomeAction);
        }

        void SomeAction(String param)
        {
            //Do Something
        }
    }


    public class Consumer
    {

        public Consumer()
        {
            MessagePump.Subscribe<Action<String>>("Foo", HandlerMethod);
        }

        void HandlerMethod(String param)
        {
            // Do Something
        }

    }

This is just something off the top of my head and is a contrived example so take it with a grain of salt. This is nearly exactly what I am doing in the courier framework I posted earlier. You may want to dive into that code to get a more concrete implementation example.

You need to think about how you will manage consumers, how you validate Broadcast and subscriptions and for your specific case how are you going to ensure the delegate you are passing around is invoked correctly? Or do you care?

Does this help?

Foovanadil