简体   繁体   中英

C# Terminate a Workflow Programatically from inside Code Activity WF 4.0

I have a code Activity hosted inside a Windows Workflow Foundation Service , I want to terminate the workflow based on some values I am checking from the database. I don't want to use the Throw Exception method, and I need to do it from inside the "Code Activity" Code, not from the designer . I am still a beginner in WWF , I tried the below method, which is creating a workflow application, and initializing it on the current instance of the code activity, but it didn't work. I need to capture the parent workflow application of the current activity instance first, then call the Terminate method.

   WorkflowApplication wfApp = new WorkflowApplication(this);
   wfApp.Terminate("The following workflow is terminating");

Thanks for your help on this

To terminate gracefully, just use TerminateWorkflow as a child activity. This will invoke WorkflowApplication.Completed action.

public class CanceledActivity : NativeActivity
{
    private readonly TerminateWorkflow terminateWorkflow = new TerminateWorkflow
        {
            Reason = "Reason why I'm terminating!"
        };

    protected override void CacheMetadata(NativeActivityMetadata metadata)
    {
        metadata.AddImplementationChild(terminateWorkflow);
    }

    protected override void Execute(NativeActivityContext context)
    {
        context.ScheduleActivity(terminateWorkflow);
    }
}

Or you can just throw an exception but this will invoke WorkflowApplication.OnUnhandledException instead.

public class CanceledActivity : NativeActivity
{
    protected override void Execute(NativeActivityContext context)
    {
        throw new Exception("this will not gracefully terminate the workflow")
    }
}

There're a bunch of other ways of doing it, also depending on what you want to do and when you want to do it. Keep in mind that workflow will only terminate when it can, due to its asynchronous nature.

You can put the WorkflowApplication into the application context extensions which will then be available through the ActivityContext class.

// Add the application to it's own context
_workflowApplication.Extensions.Add(_workflowApplication);

// Access the application in your activity
var application = context.GetExtension<WorkflowApplication>();
application.BeginTerminate(new WorkflowException(error), null, null);

It looks to me that in fact you have two activities in the one activity you currently want to use. What you are asking for is not possible in flowcharts (ie Visio) either because one activity has only one exit what can be linked to a next activity (ie an end state), you'd need a decision block to be able to take a different route.

This is an example for what you try to translate into a flowchart:

public int CalculatePrice(string parameters)
{
    // Calculate result.
    var price = 5;

    // Are we done?
    if (!IsVATNeeded(price))
    {
        return price;
    }

    // Do more calculations.
    price = price * vat;

    return price;
}

Return from within body of a method is a code smell pointing to the need of rethinking the workflow. A healthy method has only one return. Ie

public int CalculatePrice(string parameters)
{
    var price = CalculatePriceWithoutVAT(parameters);

    if (IsVATNeeded(parameters))
    {
        price = ApplyVAT(price);
    }

    return price;
}

Now this second method is straightforward to translate into a flowchart/workflow. 在此输入图像描述

If you have a different case please provide a sample flowchart or other diagram. The rule of thumb is that if you can't draw a flowchart, a state machine or sequence diagram then it can't be implemented with Microsoft Workflow.

Note that it is possible to create create activities what are composed of other activities so you could embed the activities on diagram above into a single activity and hide the details. It would be the same like CalculatePrice method in code samples. The caller doesn't actually have to know how the price is calculated.

You can just do:

throw new System.Activities.Statements.WorkflowTerminatedException("reason string");

from any where in your code and be done with it :)

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