Search code examples
c#workflowworkflow-foundationstate-machine-workflow

Cannot load instance of StateMachineStateTracker. Maybe its reach Final State in WF


First I'm totally new to WorkFlow Foundation 4.5. We use the WF engine for managing States in our Case entities. Instead of building our own state machine we decided to use WF. Mostly due to the fact that our customer have large process flows (not that complicated) that we wanted to draw in xaml. Easy for everybody to actually understand the process and talk about it.

The problem is that our transitions to the end state, Final state, results in that StateMachineStateTracker instance is null when we load it. This code below works perfectly for all transitions and we can load up tracker instance after resuming bookmark to see what the new current state is.

 private void ConfigureWorkflowApplication(WorkflowApplication wfApp, SqlWorkflowInstanceStore store)
    {
        wfApp.InstanceStore = store;
        var tracker = new StateMachineStateTracker(wfApp.WorkflowDefinition);
        wfApp.Extensions.Add(tracker);
        wfApp.Extensions.Add(new StateTrackerPersistenceProvider(tracker));
        wfApp.Completed = delegate { Debug.WriteLine("Workflow completed."); };
        wfApp.Aborted =
            delegate(WorkflowApplicationAbortedEventArgs e)
            {
                Debug.WriteLine("Workflow Aborted. Exception: {0}\r\n{1}", e.Reason.GetType().FullName,
                    e.Reason.Message);
            };
        wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
        {
            Debug.WriteLine("Unhandled Exception: {0}\r\n{1}", e.UnhandledException.GetType().FullName,
                e.UnhandledException.Message);
            return UnhandledExceptionAction.Terminate;
        };
        wfApp.PersistableIdle = delegate { return PersistableIdleAction.Unload; };
    }

Code above instantiate a WorkFlowApplication instance.

protected bool Execute(Activity process, Case @case, string transition) { WorkflowApplicationInstance instance = null; using (var store = new DisposableStore()) { instance = WorkflowApplication.GetInstance(@case.InstanceId, store.Store);

            var wfApp = new WorkflowApplication(process, WorkflowIdentity);
            ConfigureWorkflowApplication(wfApp, store.Store);
            var trackerInstance = StateMachineStateTracker.LoadInstance(@case.InstanceId, wfApp.WorkflowDefinition,
                _connectionString);
            if (!trackerInstance.Transitions.Any(x => x.DisplayName.Equals(transition))) return false; 
        }
        using (var store = new DisposableStore())
        {
            var wfApp = new WorkflowApplication(process, instance.DefinitionIdentity);
            ConfigureWorkflowApplication(wfApp, store.Store);
            wfApp.Load(@case.InstanceId);
            var sync = new AutoResetEvent(false);
            wfApp.ResumeBookmark(transition, null);
            wfApp.Unloaded = x => sync.Set();
            sync.WaitOne();

            // Set case to new state
            var trackerInstance = StateMachineStateTracker.LoadInstance(@case.InstanceId, wfApp.WorkflowDefinition,
                _connectionString);

            @case.ChangeToNewState(trackerInstance.CurrentState);
        }

        return true;
    }

The code above have the intention to Make a transition from one State to next (string transition) and we also want to set the new state to our Case class.

This fails when we want to do this from our State before Final state. No exception. No Logging in output window. Nothing. Just that the row

var trackerInstance = StateMachineStateTracker.LoadInstance(@case.InstanceId, wfApp.WorkflowDefinition, _connectionString);

Returns null. Is this due to the fact that you cannot Load StateMachineStateTracker with an instance that is on final state (not sure if it actually reaches final state).

Do anybody have any clue about the problem? I have a feeling that this is something basic that we've forgot.


Solution

  • Ok. I found the problem. It was as I though. Not a problem. Just me being rookie on WF. When you do transitions to final state, WF remove all data about case since its finished. This means SurrogateInstance is removed from DB and state machine state tracker are of course not working since there is no case to load into tracker. BUT however I did a delegate method on Completed event for WorkflowApplication that can handle closure and finalize our case.

      wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
            {
                Debug.WriteLine("Workflow completed.");
                Debug.WriteLine("State" + e.CompletionState);
                if (e.CompletionState == ActivityInstanceState.Closed)
                {
                    _caseIsCompleted = true;
                }
            };