You can do this just how you'd host it on any other kind of executable. Basically you'd create an instance of the WorkflowRuntime engine in your service as part as your OnStart operation. Any of the basic workflow hosting samples should get you started on this, or even just creating a basic Console Workflow project to see the basic code necessary.
You can also configure any necessary workflow services you require on your engine by using the app.config file or by using code (runtime.AddService()).
@Tomas, thanks for your answer. I did not know, that you can have only one runtime instance in one aplication domain - that kind of eliminates option 2 anyway. I imagine to use one receiving queue with multiple listeners on the service end. The reason for this is that once one listener thread becomes active the processing of the message might take a while (my guess is up to 10 seconds in my scenario). If I do not start a new workflow for an incoming message, I am able to identify the worklfow instance I want to send it to by the content of the message, so interacting with specific workflow instances is not a problem. The only thing I was worrying about is how the workflow runtime acts to load and if it is thread safe. But after what you said I guess a plain way (with the out-of-the-box activities) is to use the HandleExternalEvent and CallExternalMethod activities and use a service that implements some functions/events for the communication - this buddy has to be threadsafe, though, as there is only one instance of a service in the workflow runtime, too, and multiple threads will call functions on this guy to fire events to workflow instances.
@Andreas MSMQ is fairly easy, just a simple example:
This little example here works like this, A sends a message, B receives the message and sends a response back, A receveives the response. In this example there is only one queue, you might want to have a receive and send queue. Also as A waits for a special message directed to it, it waits for a correlated message, the correlation token is the message id of it's request message. B sets this correlation id on the response, so that A can receive this special message.
if (!System.Messaging.MessageQueue.Exists(".\\Private$\\MSMQTest")) System.Messaging.MessageQueue.Create(".\\Private$\\MSMQTest"); System.Messaging.MessageQueue msgq = new System.Messaging.MessageQueue(".\\Private$\\MSMQTest"); msgq.Purge(); msgq.MessageReadPropertyFilter.SetAll(); msgq.Formatter = new System.Messaging.BinaryMessageFormatter();
// Program A: someone sends a message in the queue Console.WriteLine("A: send a message"); Message msmqMsgRequest = new Message("request"); ShowMessage(msmqMsgRequest); msgq.Send(msmqMsgRequest); string requestMsgId = msmqMsgRequest.Id;
// Program B: a message is received from the queue Console.WriteLine("B: receive a message"); System.Messaging.Message msmqReceivedRequest = msgq.Receive(new TimeSpan(0, 0, 10)); ShowMessage(msmqReceivedRequest); // send response Console.WriteLine("B: send response"); MyMessage msmqResponse = new MyMessage("response"); msmqResponse.CorrelationId = msmqReceivedRequest.Id; ShowMessage(msmqResponse); msgq.Send(msmqResponse);
//Program A: waits for HIS response (probably on a separate queue) // here for the ease the same Console.WriteLine("A: receive response"); System.Messaging.Message msmqReceivedResponse = msgq.ReceiveByCorrelationId(requestMsgId, new TimeSpan(0, 0, 10)); ShowMessage(msmqReceivedResponse);
This is exactly what what I'm looking for, a windows service that will read measseges from a queue and process workflow instances accordingly, but I'dont know how to do it as I don't know how MSQM works.
Can anybody of you give me an example of this tech ... even without a workflow but with a windows service procesing messages from a queue ... If you have one with a workflow, that would be perfect
Tomas Restrepo has also created some nice Msmq workflow activities. You can just drag and drop a Msmq Receive message activity in your workflow. http://www.winterdom.com/weblog/2006/10/20/MsmqActivitiesV11Released.aspx
The part that I'm not too sure about is how to have multiple worklow instances processing messages from the queue. It's easy to start multiple workflow instances (and wrap the msmqReceive in a while loop )
Once the queue is empty the workflow should 'sleep' till the next message arrives Is that possible
I wonder if the EventDriven activitiy can wake such a workflow up again. Anybody knows how to create a forever running message queue process
Or MSMQ and a known message format (if one wants to implement it)...
But I got an addon question to this topic: Running the workflows in a service can be a bottleneck, so you want to achieve high throughput. Considering I use a message queue and have multiple listeners fetching messages from the list. Would they create a new workflowruntime to load and forward the message to the appropriate workflow instance or is the workflow runtime threadsafe so that multiple threads can and should interact with one workflow runtime instance
So to clarify the approaches again: (Considering x messages are send to the queue and y workflow instances are persisted and waiting in the persistance storage for (re)activation)
1) e..g some threads are waiting for messages in the queue. If a message is in the queue it is fetched, a workflow runtime is created, started and the message is send to the right queue. This might take a moment, so if in the meantime more messages become available another thread will fetch it and do the same.
2) there is one workflow runtime already started. Multiple threads are waiting for messages. If a message becomes available a thread fetches it from the queue and sends it to a queue to the one workflow runtime. If in the meantime more messages become available other threads do the same and the workflow runtime is accessed concurrently.
Which one is the "right" approach inside one service And how is the internal threading behavior of the workflow runtime anyway when it executes multiple workflow instances at the same time
You can only have a single WorkflowRuntime instance per appdomain, so your service would only have one runtime, running as many workflow instances concurrently.
As for contention reading from the queue, it would depend on the semantics needed and whether you mostly care about getting messages and firing new workflows or you need to interact with specific workflow instances, but there are certainly several possibilities here.
One would be to have a single queue and a single consumer thread. For each message receive a new workflow is started. Since the workflow runs in a separate thread, anyway, the consumer thread could just go back to waiting for another message in the queue.
Or you could have an different queue for each workflow type you need, and handle those concurrently.
In addition to Thomas' comments, the biggest concern will be how you connect/communicate with the workflows, unless they are going to be started and used solely within the service. Otherwise, you need to use remoting, web services, or WCF to communicate to the host and then handle routing messages to the service.
Host Workflow in Windows Service
seaside1982
You can also configure any necessary workflow services you require on your engine by using the app.config file or by using code (runtime.AddService()).
Tollo
@Tomas, thanks for your answer.
I did not know, that you can have only one runtime instance in one aplication domain - that kind of eliminates option 2 anyway.
I imagine to use one receiving queue with multiple listeners on the service end. The reason for this is that once one listener thread becomes active the processing of the message might take a while (my guess is up to 10 seconds in my scenario). If I do not start a new workflow for an incoming message, I am able to identify the worklfow instance I want to send it to by the content of the message, so interacting with specific workflow instances is not a problem. The only thing I was worrying about is how the workflow runtime acts to load and if it is thread safe. But after what you said I guess a plain way (with the out-of-the-box activities) is to use the HandleExternalEvent and CallExternalMethod activities and use a service that implements some functions/events for the communication - this buddy has to be threadsafe, though, as there is only one instance of a service in the workflow runtime, too, and multiple threads will call functions on this guy to fire events to workflow instances.
@Andreas MSMQ is fairly easy, just a simple example:
This little example here works like this, A sends a message, B receives the message and sends a response back, A receveives the response. In this example there is only one queue, you might want to have a receive and send queue. Also as A waits for a special message directed to it, it waits for a correlated message, the correlation token is the message id of it's request message. B sets this correlation id on the response, so that A can receive this special message.
if (!System.Messaging.MessageQueue.Exists(".\\Private$\\MSMQTest"))System.Messaging.MessageQueue.Create(".\\Private$\\MSMQTest");
System.Messaging.MessageQueue msgq = new System.Messaging.MessageQueue(".\\Private$\\MSMQTest");
msgq.Purge();
msgq.MessageReadPropertyFilter.SetAll();
msgq.Formatter = new System.Messaging.BinaryMessageFormatter(); // Program A: someone sends a message in the queue
Console.WriteLine("A: send a message");
Message msmqMsgRequest = new Message("request");
ShowMessage(msmqMsgRequest);
msgq.Send(msmqMsgRequest);
string requestMsgId = msmqMsgRequest.Id;
// Program B: a message is received from the queue
Console.WriteLine("B: receive a message");
System.Messaging.Message msmqReceivedRequest = msgq.Receive(new TimeSpan(0, 0, 10));
ShowMessage(msmqReceivedRequest);
// send response
Console.WriteLine("B: send response");
MyMessage msmqResponse = new MyMessage("response");
msmqResponse.CorrelationId = msmqReceivedRequest.Id;
ShowMessage(msmqResponse);
msgq.Send(msmqResponse);
//Program A: waits for HIS response (probably on a separate queue)
// here for the ease the same
Console.WriteLine("A: receive response");
System.Messaging.Message msmqReceivedResponse = msgq.ReceiveByCorrelationId(requestMsgId, new TimeSpan(0, 0, 10));
ShowMessage(msmqReceivedResponse);
Jerryk
This is exactly what what I'm looking for, a windows service that will read measseges from a queue and process workflow instances accordingly, but I'dont know how to do it as I don't know how MSQM works.
Can anybody of you give me an example of this tech ... even without a workflow but with a windows service procesing messages from a queue ... If you have one with a workflow, that would be perfect
Thanks in advance
dna2
That should help you get started, but if you have any trouble, do post and we'll help you out :)
Pranjali
Tomas Restrepo has also created some nice Msmq workflow activities. You can just drag and drop a Msmq Receive message activity in your workflow. http://www.winterdom.com/weblog/2006/10/20/MsmqActivitiesV11Released.aspx
The part that I'm not too sure about is how to have multiple worklow instances processing messages from the queue.
It's easy to start multiple workflow instances (and wrap the msmqReceive in a while loop )
Once the queue is empty the workflow should 'sleep' till the next message arrives Is that possible
I wonder if the EventDriven activitiy can wake such a workflow up again. Anybody knows how to create a forever running message queue process
bcecile
Or MSMQ and a known message format (if one wants to implement it)...
But I got an addon question to this topic: Running the workflows in a service can be a bottleneck, so you want to achieve high throughput. Considering I use a message queue and have multiple listeners fetching messages from the list. Would they create a new workflowruntime to load and forward the message to the appropriate workflow instance or is the workflow runtime threadsafe so that multiple threads can and should interact with one workflow runtime instance
So to clarify the approaches again:
(Considering x messages are send to the queue and y workflow instances are persisted and waiting in the persistance storage for (re)activation)
1) e..g some threads are waiting for messages in the queue. If a message is in the queue it is fetched, a workflow runtime is created, started and the message is send to the right queue. This might take a moment, so if in the meantime more messages become available another thread will fetch it and do the same.
2) there is one workflow runtime already started. Multiple threads are waiting for messages. If a message becomes available a thread fetches it from the queue and sends it to a queue to the one workflow runtime. If in the meantime more messages become available other threads do the same and the workflow runtime is accessed concurrently.
Which one is the "right" approach inside one service And how is the internal threading behavior of the workflow runtime anyway when it executes multiple workflow instances at the same time
Quantum00
You can only have a single WorkflowRuntime instance per appdomain, so your service would only have one runtime, running as many workflow instances concurrently.
As for contention reading from the queue, it would depend on the semantics needed and whether you mostly care about getting messages and firing new workflows or you need to interact with specific workflow instances, but there are certainly several possibilities here.
One would be to have a single queue and a single consumer thread. For each message receive a new workflow is started. Since the workflow runs in a separate thread, anyway, the consumer thread could just go back to waiting for another message in the queue.
Or you could have an different queue for each workflow type you need, and handle those concurrently.
mrpeepers
In addition to Thomas' comments, the biggest concern will be how you connect/communicate with the workflows, unless they are going to be started and used solely within the service. Otherwise, you need to use remoting, web services, or WCF to communicate to the host and then handle routing messages to the service.
Matt