WWF消息传送机制初步探讨

本文详细介绍了Windows Workflow Foundation (WWF) 中host程序与workflow之间的两种交互方式:使用事件机制和属性进行数据传递。通过具体代码示例展示了如何利用外部事件触发workflow活动以及如何设置和读取属性以实现数据交换。
1. host程序向workflow传送信息
1) 使用事件机制
host程序以winForm为例,WWF由状态机流程的handleExternalEventActivity为例,该Activity需要等待一个事件的触发才能够继续工作流的运行,而该事件的触发则由host程序上的BUTTON点击事件触发。
所有host与Workflow的通讯均要通一个实现了某个interface的class来进行,下面是interface的定义
[System.Workflow.Activities.ExternalDataExchange]//该接口必须标记有此属性
public interface IUserInterface
{
void SendMessage(IntPtr handle,DataFromWin args);//host将通过调用此方法来触发事件
event EventHandler<DataFromWin> SendNum;//该EventHandle负责向Workflow传送事件及数据,触发handleExternalEventActivity的执行,从而开始workflow。
}
比较恶心的是,MS规定向workflow传送的数据必须继承于某个特殊的class格式如handleExternal必须继承自ExternalDataEventArgs
[Serializable]//实现之前必须有此属性,该类负责传输实例化后的workflow的instanceId,以及部分host需要向workflow传送的数据,例如str就是从host端传入的
public class DataFromWin : ExternalDataEventArgs
{
private Guid documentId;
private string str;
public DataFromWin(Guid instanceId,string str)
: base(instanceId)
{
this.documentId = instanceId;
this.str = str;
}
public Guid DocumentId
{
get { return this.documentId; }
set { this.documentId = value; }
}
public string stre
{
get { return this.str; }
set { this.str = value; }
}
}
下面的类负责实现上文提到的interface:
public class UserInterface : IUserInterface
{
public void SendMessage(IntPtr handle, DataFromWin args)
{//实际上IntPtr handle 也可以放在args中传送
Console.WriteLine("hello");
if (this.SendNum != null)
this.SendNum(handle,args);//该句负责向workflow传送事件及host的数据,一旦执行该命令,则handleExternalEventActivity将开始工作
}
public event EventHandler<DataFromWin> SendNum;
}
下面转到vs的workflow设计界面,选中handleExternalEventActivity,在properties中有如下几个选项:
EventName:SendNum//选择触发该activity执行的事件,该事件是在interface中定义的
InterfaceType:Iuserinterface//选择该activity需要执行的interface
Invoked:Runit//在该activity执行过程中,需要执行的方法,注意该方法在workflow类中定义,并且签名要满足该activity的定义,如:
public void Runit(Object sender, ExternalDataEventArgs e)
{
Console.WriteLine(((DataFromWin)e).stre);
newText((IntPtr)sender);
}
下面在host中编写代码触发该activity的执行
private WorkflowLibrary1.UserInterface xx= new WorkflowLibrary1.UserInterface();
首先实例化这个负责host和workflow间数据传送的类,再次声明,此类的运行机制很重要,基本代表了wwf中各种activity的触发和数据传送机制。
workflowRuntime = new WorkflowRuntime();
ExternalDataExchangeService mmm = new ExternalDataExchangeService();
workflowRuntime.AddService(mmm);
mmm.AddService(xx);
workflowRuntime.StartRuntime();
中间3句比较有意思,wwf中,activity与外界的交流貌似都要通过各种service来实现,有得可以直接添加相应的接口实现类就可以了,有的必须要首先添加规定的service,比如这个例子,首先要向runtime中添加ExternalDataExchangeService的实例,再向ExternalDataExchangeService中添加负责数据交换的UserInterface类。有的情况下直接添加UserInterface类就ok了,搞不懂,就当这是规定吧,谁叫俺不是设计这个咚咚的人呢。
然后实例化workflow,触发workflow开始工作的代码如下
private void button1_Click(object sender, EventArgs e)
{
xx.SendMessage(this.Handle,new WorkflowLibrary1.DataFromWin(workflowInstance.InstanceId,this.textBox1.Text));
}
host调用UserInterface实例的方法,传入Handle和符合ExternalDataEventArgs的类,其中主要有2个信息,一是该workflow的实例号,二是winform界面输入的字符。感觉之所以强制数据交换类符合ExternalDataEventArgs的要求,就是为了获得workflow的实例号,防止多个workflow实例运行时消息的误传递。
紧接着this.SendNum(handle,args);将数据传入workflow,同时该事件的触发导致handleExternalEventActivity的执行从而开启整个workflow,获得启动后handleExternalEventActivity同时还将执行回调函数Runit处理传送进的数据。至此,整个从host向workflow传递数据的过程结束了。
2) 使用属性
Workflow:
public partial class Workflow1 : SequentialWorkflowActivity
{
private void codeActivity1_CodeHandler(object sender, EventArgs e)
{
System.Windows.Forms.MessageBox.Show(
"Hello, World!: " + firstName + " " + lastName);
}
private string firstName;
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
private string lastName;
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
Host宿主程序:
if (wr == null)
{
wr = new WorkflowRuntime();
wr.StartRuntime();
}
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("FirstName", txtFirstName.Text);
parameters.Add("LastName", txtLastName.Text);
WorkflowInstance instance = wr.CreateWorkflow(typeof(HelloWorldWorkflow.Workflow1), parameters);
instance.Start();
2. 从workflow向host传送数据的流程如下:
首先我的目的是在workflow运行到某一阶段的时候触发一个事件,在winform的textbox2上显示一条文本。这需要向workflow传送一个该form的handle,有2种方式传送该handle:
一是将此handle 封装在符合ExternalDataEventArgs要求的类中,也就是DataFormWin类,这比较简单也比较直观,就不说了
二是在workflow中定义一个IntPtr类型的属性,在初始化workflow的时候传入
public static DependencyProperty HandleProperty = System.Workflow.ComponentModel.DependencyProperty.Register("Handle", typeof(IntPtr), typeof(Workflow1));
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public IntPtr Handle
{
get
{
return ((IntPtr)(base.GetValue(Workflow1.HandleProperty)));
}
set
{
base.SetValue(Workflow1.HandleProperty, value);
}
}//workflow中的属性代码,so麻烦,懒得看,照着用就是了
在初始化的时候
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("Handle", this.Handle);//建立参数,将handle 传入workflow
workflowInstance = workflowRuntime.CreateWorkflow(typeof(WorkflowLibrary1.Workflow1),parameters);//初始化
workflowInstance.Start();
之后在vs的workflow设计界面handleExternalEventActivity的sender属性上选择Handle就ok了。
数据传入后,以下的处理都差不多
首先,定义delegate:public delegate void textBoxuseEventHandler(IntPtr Handle);
其次,在workflow类中初始化:public static textBoxuseEventHandler newText;
再次,在Runit中触发newText(((DataFromWin)e).Handle);
在host端订阅WorkflowLibrary1.Workflow1.newText = TextShow;
public void TextShow(IntPtr handle)
{
Form1 form = (Form1)(Form1.FromHandle(handle));
if (form != null) form.MessageReceive("12133dsfdsf");
}
public void MessageReceive( string message)
{
if (this.InvokeRequired)
{
MessageDisplayDelegate messageDisplay = new MessageDisplayDelegate(this.MessageReceive);
this.Invoke(messageDisplay, message);
}
else
{
this.textBox2.Text += message;
}
}
特别注意黑体的代码,如果没有这行,则会出现cross-thread访问异常。
内容概要:本文详细介绍了“秒杀商城”微服务架构的设计与实战全过程,涵盖系统从需求分析、服务拆分、技术选型到核心功能开发、分布式事务处理、容器化部署及监控链路追踪的完整流程。重点解决了高并发场景下的超卖问题,采用Redis预减库存、消息队列削峰、数据库乐观锁等手段保障数据一致性,并通过Nacos实现服务注册发现与配置管理,利用Seata处理跨服务分布式事务,结合RabbitMQ实现异步下单,提升系统吞吐能力。同时,项目支持Docker Compose快速部署和Kubernetes生产级编排,集成Sleuth+Zipkin链路追踪与Prometheus+Grafana监控体系,构建可观测性强的微服务系统。; 适合人群:具备Java基础和Spring Boot开发经验,熟悉微服务基本概念的中高级研发人员,尤其是希望深入理解高并发系统设计、分布式事务、服务治理等核心技术的开发者;适合工作2-5年、有志于转型微服务或提升架构能力的工程师; 使用场景及目标:①学习如何基于Spring Cloud Alibaba构建完整的微服务项目;②掌握秒杀场景下高并发、超卖控制、异步化、削峰填谷等关键技术方案;③实践分布式事务(Seata)、服务熔断降级、链路追踪、统一配置中心等企业级中间件的应用;④完成从本地开发到容器化部署的全流程落地; 阅读建议:建议按照文档提供的七个阶段循序渐进地动手实践,重点关注秒杀流程设计、服务间通信机制、分布式事务实现和系统性能优化部分,结合代码调试与监控工具深入理解各组件协作原理,真正掌握高并发微服务系统的构建能力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值