博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WF(9):本地服务之事件处理
阅读量:6040 次
发布时间:2019-06-20

本文共 4771 字,大约阅读时间需要 15 分钟。

一:先来介绍两个活动 EventDrivenActivity和 ListenActivity。

EventDrivenActivity是一个等侍事件触发的容器,EventDrivenActivity第一个子结点必需是一个继承 IEventActivity接口的Activity,后面所有的结点可以是任意Activity。该活动必须具有父级活动,它的父级活动可以是 ListenActivity,StateActivity或StateMachineWorkflowActivity。

如果EventDrivenActvity在状态机工作流中使用,还有如下使用限制:

1. EventDrivenActivity 可以并且只能包含一个实现了IEventActivity接口的Activity.如HandleExternalEvent或Delay。

2. 如果有 HandleExternalEventActivity 必须是第一个结点.这是因为,Windows Workflow Foundation 实现的状态机工作流模型一次只处理一个EventDrivenActivity活动。例如,如果EventDrivenActivity 活动中包含多个能够运行的 IEventActivity 活动,则会出现以下情况:某个 EventDrivenActivity 活动在等待可能永远不会执行的IEventActivity 时被阻止。这样,状态机将无法处理任何其他消息。
3. 一个StateActivity状态容器可以有多个EventDrivenActivity。

ListenActivity属于单线触发容器,当某条分支中的结点执行完成后,该ListenActivity结点就结束,继续向下执行,其他分 支内的结点就不执行了。EventDrivenActivity是它唯一可以添加的子活动,并且至少必须有两个子活动。该活动无法用于状态机工作流中。

二:工作流能够使用方法和事件通过消息与宿主程序交互。 事件用于将数据发送到工作流,而工作流使用方法将数据发送到主机应用程序。在坚持学习WF(8):本地服务之调用外部方法这篇中我们说明了工作流如何使用 本地服务来调用外部方法,接下来我们用一个猜数字游戏的小例子来主要说明在本地服务中如何使用事件。调用外部方法和事件处理基本的流程差不多。

1.实现事件参数类,GuessReceivedEventArgs类需要继承自ExternalDataEventArgs类,ExternalDataEventArgs类中的instanceId可以保证正确的工作流实例来接收事件

using
 System;
using
 System.Workflow.Activities;
namespace
 GuessNumber
{
    
    [Serializable]
    
public
 
class
 GuessReceivedEventArgs : ExternalDataEventArgs
    
{
        
private
 Int32 _nextGuess;
        
public
 GuessReceivedEventArgs(Guid instanceId, Int32 nextGuess)
            : 
base
(instanceId)
        
{
            _nextGuess 
=
 nextGuess;
        }
        
public
 Int32 NextGuess
        
{
            
get
 
return
 _nextGuess; }
            
set
 
{ _nextGuess 
=
 value; }
        }
    }
}
2.定义服务接口,代码如下

 

using
 System;
using
 System.Workflow.Activities;
namespace
 GuessNumber
{
    [ExternalDataExchange]
    
public
 
interface
 IGuessingGame
    
{        
        
void
 SendMessage(String message);       
        
event
 EventHandler
<
GuessReceivedEventArgs
>
 GuessReceived;
    }
}

3.实现本地服务,先定义一个事件参数。

这个也继承自ExternalDataEventArgs,虽然它不是用在工作流中,但是我们为了使用InstanceId,所以也让它继承这个类。

 

using
 System;
using
 System.Workflow.Activities;
namespace
 GuessNumber
{
    [Serializable]
    
public
 
class
 MessageReceivedEventArgs : ExternalDataEventArgs
    
{
        
private
 String _message;
        
public
 MessageReceivedEventArgs(Guid instanceId, String message)
            : 
base
(instanceId)
        
{
            _message 
=
 message;
        }
        
public
 String Message
        
{
            
get
 
return
 _message; }
            
set
 
{ _message 
=
 value; }
        }
    }
}

本地服务类,这类中共有四个成员:

SendMessage:workflow使用,由工作流实例来调用,发送一个信息到宿主程序,并且激发MessageReceive事件。

GuessReceived:workflow使用,接收下一个猜的数字,当OnGuessReceived方法调用的时候激发。

MessageReceived宿主使用,从工作流实例接收一个信息,通过SendMessage方法激发。

OnGussReceived:宿主使用,发送一个新的猜的数字到工作流,会引发GuessReceived事件。

注意:SendMessage方法使用静态的WorkflowEnvironment.WorkflowInstanceId方法取回工作流实例的ID,WorkflowEnvironment表示正在当前线程中运行的工作流实例的事务环境。

using
 System;
using
 System.Workflow.Runtime;
namespace
 GuessNumber
{
    
public
 
class
 GuessingGameService : IGuessingGame
    
{       
        
public
 
void
 SendMessage(
string
 message)
        
{
            
if
 (MessageReceived 
!=
 
null
)
            
{
                MessageReceivedEventArgs args
                    
=
 
new
 MessageReceivedEventArgs(
                        WorkflowEnvironment.WorkflowInstanceId,
                        message);
                MessageReceived(
this
, args);
            }
        }
        
        
public
 
event
 EventHandler
<
GuessReceivedEventArgs
>
 GuessReceived;   
        
public
 
event
 EventHandler
<
MessageReceivedEventArgs
>
 MessageReceived;
        
public
 
void
 OnGuessReceived(GuessReceivedEventArgs args)
        
{
            
if
 (GuessReceived 
!=
 
null
)
            
{
                
//
must pass null as the sender otherwise
                
//
the correct workflow won't receive the event.
                GuessReceived(
null
, args);
            }
        }
        
    }
}
4.设计工作流,在工作流的Initialized事件中初始化这个要猜的随机数。
private
 
void
 OnInitialized(
object
 sender, EventArgs e)
{
Random random 
=
 
new
 Random();
_theNumber 
=
 random.Next(
1
10
);
Message 
=
 
"
Please guess a number between 1 and 10.
"
;
}

Message属性给宿主的程序的暗示信息,指示猜的数字是大了还是小了。IsComplete属性是WhileActivity使用的,决定工作流是否完成了。

通过活动CallExternalMethodActivity设置InterfaceType和MethodName,还有message属性。

GuessReceived事件:在GuessReceived被激发的时候执行 handleExternalEventActivity1_Invoked。该事件中决定用户的猜测是大了还是小了,为了完成工作流你必须处理该事件永 远不发生的情况,我们要拖一个CodeActivity在右边的Event-Driven中,设置事件为一分钟,然后在拖一个 TeminalActivity,如果一分钟内没猜的话就结束了。

完整的工作流如下图:

完整代码如下

 

 

GuessingGameWorkflow.cs

实现宿主程序,代码如下

Form1.cs

宿主程序使用的windows窗体,最终效果如下图:

 
 

三:使用CallExternalMethodActivity和HandleExternalEventActivity可以和本地服务通信,但 是我们需要设置他们的InterfaceType,MethodName或EventName。wca.exe是一个命令行工具,包含在windows SDK中,使用wca.exe,你可以生成一组强类型的自定义活动。这个命令行工具叫Workflow communication activity generator 。具体的参数可以在MSDN上查阅到。我们以上面例子来生成自定义通信活动(Wca /collapseArgs filepath.dll[.exe]),如下图:

该工具会自动查找.dll或.exe中标有[ExternalDataExchange]的接口,结束后会生成接口名+Invokes.cs和接口 名+ Sinks.cs 的两个文件,IGuessingGame.Invokes.cs和IGuessingGame.Sinks.cs。第一个自定义活动 SendMessage使用CallExternalMethodActivity作为基类,第二个自定义活动GuessReceived 使用HandleExternalEventActivity作为基类,然后我们就可以把这两个文件加入到项目中,重新生成就会在工具箱中出现了.

 

修改工作流宿主

在上面例子的基础上删除callExternalMethodActivity1和callExternalMethodActivity2。用刚 才生成的SendMessage活动代替,绑定message参数属性。用GuessReceived代替 handleExternalEventActivity1,绑定invoke事件即可。运行工作流效果和上面的是一样的。

本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/archive/2012/03/01/2375974.html,如需转载请自行联系原作者

你可能感兴趣的文章
微信小程序初体验(上)- 腾讯ISUX社交用户体验设计成员出品
查看>>
SAP WM Physical Inventory Method ST & PZ
查看>>
一次快速的数据迁移感悟
查看>>
MySQL修改提示符
查看>>
《ELK Stack权威指南(第2版)》一3.6 Java日志
查看>>
C++流的streambuf详解及TCP流的实现
查看>>
《量化金融R语言初级教程》一2.5 协方差矩阵中的噪声
查看>>
mysql到elasticsearch数据迁移踩坑实践-Ali0th
查看>>
Python轻量级数据分析库DaPy
查看>>
beetl 和 shrio 结合
查看>>
相对/绝对路径,cd命令,mkdir/rmdir命令,rm命令
查看>>
tomcat中web.xml各配置项的意义
查看>>
Nodejs学习笔记(二):《node.js开发指南》代码中需要注意的几点
查看>>
Ztree异步加载自动展开节点
查看>>
反射操作公共成员变量
查看>>
Android热修复升级探索——代码修复冷启动方案
查看>>
学校宿舍的深夜之思考
查看>>
VB.NET 生成DBF文件
查看>>
编译安装nginx 1.9.15
查看>>
我的友情链接
查看>>