一起学WF3.5【12】


在宿主应用程序程序中检索工作流数据

上节中,我们已经创建好了外部服务类和工作流。现在试着在宿主应用中创建和启用工作流,并接收来自工作流的消息和数据。

界面设计如下图,具体上节已有描述:


同样复制WorkflowFactory类到项目中以复用。

在宿主中关键要做的是勾住MVDataUpdate事件以便使应用程序知道接收数据的时间。

在“RetrieveMV Data”的点击响应函数中,加如下代码:

MVDataService.WorkflowMVDataServicedataService =

             MVDataService.WorkflowMVDataService.CreateDataService(

                           _workflowInstance.InstanceId,

                            _workflowRuntime);

 

dataService.MVDataUpdate+= new EventHandler<MVDataService.MVDataAvailableArgs>(dataService_MVDataUpdate);

定义事件处理函数dataService_MVDataUpdate函数:(略,见附件代码),捕捉了数据获取完成事件并填充了ListView控件。

用InvokeWorkflow调用外部工作流

InvokeWorkflow可用来在正在执行的工作流中启动另一个工作流。

可按如下方法做一个例子:

新建一个顺序工作流库命名为“Workflow1”。在工作流设计器上拖一个Code活动, 可令它输出一个提示信息。同样新建一个顺序工作流库命名为Workflow2。在工作流器上上拖一个Code活动并令它输出另一个信息。编译Workflow2,并为Workflow1添加对它的引用。

回到Workflow1的设计器上,拖一个InvokeWorkflow活动到设计器上。这个新活动的有一个属性“TargetWorkflow”,点击它的浏览弹出“浏览和选择一个.NET类型”的对话框,选择Workflow2。

同样建立宿主应用。添加如下代码启动Workflow1:

WorkflowInstanceinstance = workflowRuntime.CreateWorkflow(typeof(Workflow1.Workflow1));

Instance.Start();

为宿主应用添加工作流完成事件的处理程序代码如下,以使两个工作流在完成时通知我们:

if(e.WorkflowDefinition is Workflow1.Workflow1)

            {

               Console.WriteLine("Workflow1 completed.");

            }

            else

            {

               Console.WriteLine("Workflow2 completed.");

            }

要设置AutoResetEvent,以便强制应用程序等待工作流完成。编译运行如下图,输出信息的顺序可能会有所不同:

 

逻辑流活动

WF提供了基于运行时的条件进行逻辑处理控制流的活动。包括IfElse活动、While活动和Replicator活动。

对于条件的处理既可以依靠CodeCondition处理,也可使用RuleCondition,后者使用了WF的基于规则的处理方式。

示例:Qustioner应用程序

本示例依然是一个Windows Form应用程序。它会回答你三个问题,问题内容可修改,你可指定这三个问题是各自独立还是相互关联。

当工作流开始执行时你要把这些问题和相关的情况传入工作流。相互关联的问题只有在前面的问题回答正确时才被进一步提出;各自独立的问题要求你必须回答。

 

按照上一章的模式,我们需要生成一个活动以实现宿主应用和工作流之间的通信。创建项目命名为QuestionService活动。创建过程不再赘述,项目的结构与之前的类似,我们把精力集中在实现工作流上。

 

使用IfElse活动实现

IfElse活动要求你提供一个条件表达式,它其实是一个EventHandler,有一个ConditionalEventArgs参数,有一个Boolean类型的Result属性。IfElse活动根据Result的值来选择执行分支的哪一支,两个分支都可作为其他活动的容器。

在QuestionService项目中已使用工具生成了一个通信活动:SendResponseDataToHost。

工作流项目被命名为QuestionFlow,在设计视图上,拖一个IfElse活动。在其Condition属性设置为代码条件,展开后  输入AskQuestion1。拖两个Code活动到左右两个分支,左边的ExcudeCode设置为AffirmQ1,右边的设置为NegateQ1。

工作流类需要设置如下字段和属性包含三个问题,作为启动工作流时的参数:

privatestring[] _questions = null;

publicstring[] Questions

{

get{ return_questions; }

set{ _questions = value; }

}

添加Dependent属性标记这些问题是否关联:

privatebool_dependent = true;

publicboolDependent

{

get{return_dependent; }

set{_dependent = value; }

}

回答的结果应作如下存储:

private bool[] _response = null;

它的初始化在构造器里进行:

_response =new bool[3];

_response[0]= false;

_response[1]= false;

_response[2]= false;

AskQuestion1事件处理添加如下代码:

DialogResultresult = MessageBox.Show(Questions[0], "Questioner:",

MessageBoxButtons.YesNo,MessageBoxIcon.Question);

e.Result =(result == DialogResult.Yes);

NegateQ1添加如下代码:

_response[0]= false;

if(Dependent)

{

// Negateremaining answers.

_response[1]= false;

_response[2]= false;

}

AffirmQ1添加:

_response[0]= true;

以上就完成了对第一个问题的回答。对于第2、3个问题同样加两个IfElse活动进去。事件处理程序分别为AskQuestion2、NegateQ2、AffirmQ2…。

AskQuestionQ2的代码如下:

if(_response[0]== false&& Dependent)

{

// No need toask!

e.Result =false;

}

else

{

// Ask thequestion!

DialogResultresult = MessageBox.Show(Questions[1], "Questioner:",

MessageBoxButtons.YesNo,MessageBoxIcon.Question);

e.Result =(result == DialogResult.Yes);

}

NegateQ2如下:

_response[1]= false;

if(Dependent)

{

// Negateremaining answer

_response[2]= false;

}

AffirmQ2如下:

_response[1]= true;

 

同样,AskQuesionQ3代码如下:

if(_response[1]== false&& Dependent)

{

// No need toask!

e.Result =false;

}

else

{

// Ask thequestion!

DialogResultresult = MessageBox.Show(Questions[2], "Questioner:",

MessageBoxButtons.YesNo,MessageBoxIcon.Question);

e.Result =(result == DialogResult.Yes);

NegateQ3代码如下:

_response[2]= false;

AffirmQ3代码如下:

_response[2]= true;

 

拖SendResponseDataToHost活动到工作流设计器上第三个IfEsle下边。把它的response属性设置为三个False(点浏览按钮后弹出的Boolean集合编辑器中设置)。

还需要把保存了问题问答结果的数组的值和SendResponseDataToHost活动联系起来。我们拖一个Code活动到第三个IfElse活动和SendResponseDatToHost之间。把它的ExecuteCode属性设置为CopyResponse,其代码如下:

sendResponseDataToHost1.responses= _response;

好了,编译运行。

 

使用While活动实现

上例如果使用While活动实现会更好些。我们将使用While活动替换上例。同样它也使用ConditionalEventArgs来返回你的判断结果,如果Result属性为true继续循环,false则终止循环。

在工作流设计视图中拖一个While活动。在它的Condtion属性中输入TestComplete。

拖一个Code活动到WhileActivity1中,把它的ExecuteCode属性值设为AskQuestion。

把SendResponseDataToHost活动拖入放在While活动下。

同样需要设置上例中的一些字段和属性,包括存储问题的数组和属性,是否依赖的字段和属性以及回答的数组和属性。

添加如下代码:

private Int32_qNum = 0;

TestComplete事件处理程序添加如下代码:

if(_qNum>= Questions.Length)

{

// Assignoutgoing data.

sendResponseDataToHost1.responses= _response;

// Done, soexit loop.

e.Result =false;

}

else

{

// Not done,so continue loop.

e.Result =true;

}

在AskQuestion事件处理程序中添加如下代码:

DialogResultresult = MessageBox.Show(Questions[_qNum], "Questioner:",

MessageBoxButtons.YesNo,MessageBoxIcon.Question);

_response[_qNum]= (result == DialogResult.Yes);

// Checkresponse versus dependency

if(!_response[_qNum]&& Dependent)

{

// Negateremaining questions

while(_qNum< Questions.Length)

{

// Negatethis question

_response[_qNum]= false;

// Next question

++_qNum;

}

} // if

else

{

// Set up fornext iteration

++_qNum;

}

同样放一个Code活动到While活动下把问题结果数组传给SendResponseDataToHost活动。编译执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值