This articleArticleThanks for the enthusiastic help and support from Cristina Manu of Microsoft's parallel computing platform. Some points in this series come from her published articles.
Special thanks to Cristina for her great support on this article. some Ideas of this series come from her paper "workflow and parallelextensions in. NET framework 4 ". cristina Manu is SDET at Microsoft, working for parallel computing platform.
We have discussed how to create a customizable universal concurrent workflow to implement the core component system of Microsoft's parallel architecture. threading. tasks. task encapsulation. You only need to drag the workflow activity instance to the parallel activity and bind the input and output parameters and the task to be executed to implement parallel processing of business processes. How can we name the activity to be constructed asyncparallelactivity?
We will not elaborate on the basic technologies of this series, wf4, and Microsoft's parallel computing solutions here. If necessary, we will add them later, because the introduction of these solutions is not the focus of this series for the moment.
To design such a component, we need to solve the following problems.
1) due to the uncertainty of input parameters (designers cannot know the user's business data model now, we must use generics to solve the problem of input data diversity .), Therefore, this component must support generics.
2) The user processing logic must be encapsulated, and our components cannot support any type of processing functions, because the user processing logic must be associated with the input parameter type.
(1) We first implement business encapsulation without data returned. here we can use the action <t> generic delegate in. NET Framework 2.0 to look at its function signature.
Public Delegate void action <in T> (t obj)
The return type is void, which meets our needs.
(2) the business logic of the returned data type is encapsulated below.
In the second seriesCode, We rewrite it:
/// <Summary>
/// Wrapper class for system. Threading. Tasks. task, extended from asynccodeactivity
/// </Summary>
/// <Typeparam name = "T"> </typeparam>
Public Class Asyncparallelactivity < T > : Asynccodeactivity
{
/// <Summary>
/// Input argument for Business Object with type of T
/// </Summary>
[Requiredargument]
Public Inoutargument < T > Data
{
Get ;
Set ;
}
/// <Summary>
/// Input argument for business action, as action <T>
/// </Summary>
[Requiredargument]
Public Inargument < Action < T > Function
{
Get ;
Set ;
}
Protected Override Iasyncresult beginexecute (asynccodeactivitycontext context, asynccallback callback, Object State)
{
VaR data = Data. Get (context );
VaR Function = Function. Get (context );
If (Data = Null ) Throw New Argumentnullexception ( " Data " );
If (Function = Null ) Throw New Argumentexception ( " Function " );
// Use task to wrap the action
Task worker = Task. Factory. startnew (o) =>
{
Function (data );
}, State );
Worker. continuewith (Task => Callback (task ));
Return Worker;
}
Protected Override Void Endexecute (asynccodeactivitycontext context, iasyncresult result)
{
}
Let's test our asynchronous concurrent workflow activity based on parallel computing.
(1) first define an orderservice. orderservice encapsulates the user's business logic. It has two methods to copy order information to the part and vehicle databases, which take five seconds respectively.
It takes 10 seconds for serial processing. The total parallel time is 5 seconds (other overhead is not considered ).
Public Class Orderservice
{
Public Void Dopartreplication (order)
{
Order. ID = Guid. newguid ();
Thread. Sleep ( 5000 );
}
Public Void Dovehiclereplication (order)
{
Order. Customer = " Client 123 " ;
Thread. Sleep ( 5000 );
}
}
Next we will define a new simplified order processing process.
(1) first, we define a new workflow named workflow1.
Drag a flowchart in the new workflow and define two variables in the Root Activity of the flowchart. Orderinprocess and orderservice,
Order and orderservice instances, respectively, and set their default values as new instances. As shown in.
(2) double-click parallel to add an asyncparallelactivity instance. (compile the project before adding it. The new workflow activity will appear at the top of the toolbox)
Drag two asyncparallelactivities and set the generic parameter to the order type.
Then set the input parameters for the two instances (Microsoft workflow only supports VB.net, and it is a little bit of a cup that is familiar with C # Just like me)
Data = orderinprocess
Function = new action (of order) (addressof orderservice. dopartreplication)
And
Data = orderinprocess
Function = new action (of order) (addressof orderservice. dovehiclereplication ),
Then modify the code in main.
Static Void Main ( String [] ARGs)
{
// Inprocess call Workflow
Datetime dtstart = Datetime. now;
Console. writeline ( " Workflow start time {0} " , Dtstart );
Workflowinvoker. Invoke ( New Workflow1 ());
Datetime dtend = Datetime. now;
Console. writeline ( " Workflow end time {0} " , Dtend );
Console. writeline ( " Total time elapsed {0} " , (Dtend - Dtstart). Seconds );
Console. Read ();
}
View the execution result (for better performance, execute the compiled EXE file instead of running the original code in Visual Studio)
We can see that two business flows (modifying the orderinprocess ID and customer information respectively) have been executed, and the total time is only 5 seconds. The concurrency is successful !!
In the following sections, we will improve the current example, perform various performance analysis, implement a complete solution, and finally discard Microsoft's parallel activity (because it is a fake parallel workflow activity !)
-Hu yiqian Yu 2011.5.28
Source codeDownload from here.
http://files.cnblogs.com/huyq2002/WorkflowConsole.zip