/// <summary> /// Runs this instance. /// </summary> public override void Run() { Trace.WriteLine("Starting processing of messages"); // Initiates the message pump and callback is invoked for each message that is received, calling close on the client will stop the pump. this.Client.OnMessage( receivedMessage => { try { this.resetEvent = new ManualResetEvent(false); // Process the message Trace.WriteLine( "Processing Service Bus message: " + receivedMessage.SequenceNumber.ToString()); // Name of workflow to trigger. var workflowToTrigger = receivedMessage.Properties["workflowName"]; // Prepare input message for Workflow. var channelData = new ChannelData { Payload = receivedMessage.GetBody <HostQueueMessage>() }; this.arrivedMessage = channelData.Payload; // You can save the workflow xaml externally (usually database). See this. var workflowXaml = File.ReadAllText($"{workflowToTrigger}.txt"); if (!string.IsNullOrWhiteSpace(workflowXaml)) { //// 5. Compose WF Application. var workflowApplication = new WorkflowApplication( Routines.CreateWorkflowActivityFromXaml(workflowXaml, this.GetType().Assembly), new Dictionary <string, object> { { "ChannelData", channelData } }); //// 6. Extract Request Identifier to set it as identifier of workflow. this.SetupWorkflowEnvironment( workflowApplication, channelData.Payload.WorkflowIdentifier); //// 7. Test whether this is a resumed bookmark or a fresh message. if (channelData.Payload.IsBookmark) { //// 8.1. Make sure there is data for this request identifier in storage to avoid errors due to transient errors. if (null != this.repository.GetById( "WorkflowInstanceStoreData", channelData.Payload.WorkflowIdentifier.ToString())) { //// Prepare a new workflow instance as we need to resume bookmark. var bookmarkedWorkflowApplication = new WorkflowApplication( Routines.CreateWorkflowActivityFromXaml( workflowXaml, this.GetType().Assembly)); this.SetupWorkflowEnvironment( bookmarkedWorkflowApplication, channelData.Payload.WorkflowIdentifier); //// 9. Resume bookmark and supply input as is from channel data. bookmarkedWorkflowApplication.Load(channelData.Payload.WorkflowIdentifier); //// 9.1. If workflow got successfully completed, remove the host message. if (BookmarkResumptionResult.Success == bookmarkedWorkflowApplication.ResumeBookmark( bookmarkedWorkflowApplication.GetBookmarks().Single().BookmarkName, channelData, TimeSpan.FromDays(7))) { Trace.Write( Routines.FormatStringInvariantCulture("Bookmark successfully resumed.")); this.resetEvent.WaitOne(); this.Client.Complete(receivedMessage.LockToken); return; } } else { //// This was a transient error. Trace.Write(Routines.FormatStringInvariantCulture("Error")); } } //// 10. Run workflow in case of normal execution. workflowApplication.Run(TimeSpan.FromDays(7)); Trace.Write( Routines.FormatStringInvariantCulture( "Workflow for request id has started execution")); this.resetEvent.WaitOne(); } } catch { // Handle any message processing specific exceptions here } }); this.CompletedEvent.WaitOne(); }