简体   繁体   中英

WF 4.5 Bookmarked custom activity not fire persist/unload

I've an application that host WF4.5 workflow in IIS using WorkflowServiceHost, WorkflowServiceHostFactory and WorkflowHostingEndpoint.

The workflow is defined by VS 2013 in a .xaml file. In the workflow a have a custom activity for receive input data from a user. Get that using CreateBookmark and the callback for Resume.

My problem is: The first activity execute and the workflow instance goes to idle, persist and unload. After resuming the first bookmark the second activity execute an the workflow instance goes to only idle. Thus only the first activity make workflow instance to persist and unload.

To verify that my host implementation works, i used a Delay activity and everything works.

My custom activity:

public sealed class WaitForResponse<TResult> : NativeActivity<TResult>
{
    public string ResponseName { get; set; }

    protected override bool CanInduceIdle
    {
        get
        {
            return true;
        }
    }

    protected override void Execute(NativeActivityContext context)
    {
        context.CreateBookmark(this.ResponseName, new BookmarkCallback(this.ReceivedResponse));            
    }

    protected void ReceivedResponse(NativeActivityContext context, Bookmark bookmark, object obj)
    {
        this.Result.Set(context, (TResult)obj);
    }
}

IWorkflowCreation client = new ChannelFactory<IWorkflowCreation>(new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), new EndpointAddress("net.pipe://localhost/workflowCreationEndpoint")).CreateChannel();

//create an instance
Guid id = client.Create(null);

// Resume        
client.ResumeBookmark(id, "1", "Message 1");

After a conclusion of a bookmarked activity(createbookmark/resume) the instance no more persist/unload.

In other words, only the first bookmarked activity set instance do unload. And yes , I've set TimeToPersist/TimeToUnload.

Here is the tracking status of the instance: Started, Idle, Persisted, Unloaded , Resumed, Idle, Idle, Idle, Idle, Idle, Completed, Deleted .

I created a sample solution that demonstrates the problem. Sample for download.

I really appreciate if someone could help me. Thank you for any help!

Thank you for any help!

A workflow instance will persist at runtime only when it enters a persistable state, either when it goes idle or Persist activity is used.

WorkflowServiceHost doesn't give you much control over when workflow instance is persisted but you can configure the when . Check How to: Configure Idle Behavior with WorkflowServiceHost .

Quoting:

Workflows go idle when they encounter a bookmark that must be resumed by some external stimulus, for example when the workflow instance is waiting for a message to be delivered using a Receive activity. WorkflowIdleBehavior is a behavior that allows you to specify the time between when a service instance goes idle and when the instance is persisted or unloaded. It contains two properties that enable you to set these time spans. TimeToPersist specifies the time span between when a workflow service instance goes idle and when the workflow service instance is persisted. TimeToUnload specifies the time span between when a workflow service instance goes idle and when the workflow service instance is unloaded, where unload means persisting the instance to the instance store and removing it from memory

<behaviors>
    <serviceBehaviors>
        <behavior name="">
            <workflowIdle timeToUnload="0:05:0" timeToPersist="0:04:0"/> 
        </behavior>
    </serviceBehaviors>
</behaviors>

Note that the default value for timeToPersist is MaxValue . So, although your custom activity goes idle because you're creating a bookmark, it never persists (at least for a long!! time).

EDIT:

After playing with your sample and reading some documentation, what you need to do is to call SendResponse within OnResolveBookmark

protected override Bookmark OnResolveBookmark(object[] inputs, OperationContext operationContext, WorkflowHostingResponseContext responseContext, out object value)
{
    Bookmark bookmark = null;
    value = null;
    if (operationContext.IncomingMessageHeaders.Action.EndsWith("ResumeBookmark"))
    {
        //bookmark name supplied by client as input to IWorkflowCreation.ResumeBookmark
        bookmark = new Bookmark((string)inputs[1]);
        //value supplied by client as argument to IWorkflowCreation.ResumeBookmark
        value = (string)inputs[2];

        // !!! Call it here, for example. !!!
        responseContext.SendResponse(null, null);
    }
    else
    {
        throw new NotImplementedException(operationContext.IncomingMessageHeaders.Action);
    }

    return bookmark;
}

This is briefly pointed out here :

Override OnResolveBookmark to manually extract the bookmark from the incoming message. If you override this method, you must invoke SendResponse in its body so as to respond to the message sent to the WorkflowHostingEndpoint

I don't known if this can be seen as a bug or not. The workflow engine seems to get into a state where, although it goes idle because you're giving it a bookmark, it doesn't really known it because a response warning about it is never sent.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM