I have a well defined service contract which exposes a bunch of methods. We have a typical service implementation of this contract which is hosted within IIS 7 along with our MVC App.
The architecture is of a typical distributed application with the interface defined in a base core library (which is re-distributable), the implementation within an independent services library and finally the MVC App exposing an end-point for the implementation(which is within the services library).
The situation now is that one of these existing service methods needs to possibly execute a logical process which can take upto 10 minutes to execute. In a normal scenario we would have considered workflow services but the interface under question is well in use, we have a suite of unit tests to test our services etc. and we really can't get away with this implementation that we have.
So my questions are -
WorkflowApplication
to execute your workflow definition. This will take care of executing/tracking each WF instances with the WF runtime on WF runtime specific threads (i.e. not blocking a WCF I/O thread).WorkflowApplication
instance from 1 to start the WF using the async BeginRun
and, if you care about tracking completion/errors in your WCF service, you can register the necessary Aborted
, Completed
, Unloaded
handlers.Here's a really simple example:
[DataContract]
public class MyParametersDataContract
{
[DataMember(Order=1, IsRequired=true)]
public string SomeValue
{
get;
set;
}
}
public class IMyService
{
[OperationContract(IsOneWay=true)]
void DoSomething(MyParametersDataContract someParameters);
}
public class MyService : IMyService
{
// Hold your WF definition in a static singleton to reduce overhead of activity realization
public static readonly Lazy<MyFancyWorkflow> MyWorkflow = Lazy<MyFancyWorkflow>(() => new MyFancyWorkflow());
public void DoSomething(MyParametersDataContract someParameters)
{
// Example of translating incoming parameters to WF args
Dictionary<string, object> workflowInputArguments = new Dictionary<string, object>
{
{ "SomeArgument", someParameters.SomeValue }
};
// Create a WFA instance for this request
WorkflowApplication workflowApplication = new WorkflowApplication(MyService.MyWorkflow.Value, workflowInputArguments);
// Example of hooking the completed action
workflowApplication.Completed = (workflowCompletedArgs) =>
{
// do something when workflow has completed
};
// Invoke the running of the WF asynchronously
Task.Factory.FromAsync(
workflowApplication.BeginRun,
workflowApplication.EndRun,
null)
.ContinueWith(runAntecdent =>
{
// Observe/log any exception with starting the WF so it doesn't crash the process
Trace.TraceWarning("WF failed to run: " + runAntecedent.Exception.ToString());
},
TaskContinuationOptions.OnlyOnFaulted);
}
}