`

坚持学习WF(11):工作流通信与队列

阅读更多

 

[置顶]坚持学习WF文章索引

WF 提供的通信模型是构建于队列系统的基础之上,我们可以使用自定义活动来注册以接收关于队列的消息,而宿主应用程序中的服务则发送关于队列的消息。自定义活动可以使用此模型来处理外部事件,也可以传递异步活动执行的完成。这样,您的活动可以先执行到某一点,然后等待激发因素的到来以便继续执行。下图描述了宿主应用程序中的代码与工作流中的代码(或活动)之间的通信模型。

CouQueue

下面这张图是WF类库中和队列相关的三个类:

QueueClass

为了使自定义活动能够侦听消息是否到达某个队列,我们通常有以下步骤:

1.使用WorkflowQueuingService 创建工作流队列,该类还提供了创建、查找或删除工作流队列所需的方法。一般我们会在自定义活动的 Initialize 或 Execute 方法中来实现。

2.自定义活动必须注册才能接收到这些通知,方法是在工作流队列自身中注册 QueueItemAvailable 事件。您可以使用 RegisterForQueueItemAvailable 方法为 QueueItemAvailable 事件注册一个订户。QueueItemAvailable事件用于通知订户项已经传送(以异步方式)至此 WorkflowQueue。在确保队列存在并注册事件后,当队列中有可用项目时,您的活动会得到通知,之后,您可以从队列中取出该项目并对其进行处理。

3.我们自定义活动要能够充当事件接收器的活动(如 HandleExternalEvent 活动),您还需要实现 IEventActivity 接口。如果您的活动要侦听事件,则此接口用于定义该活动的主要职责:

public interface IEventActivity 
{
    
void Subscribe(ActivityExecutionContext parentContext, IActivityEventListener<QueueEventArgs> parentEventHandler);
    
void Unsubscribe(ActivityExecutionContext parentContext, IActivityEventListener<QueueEventArgs> parentEventHandler);
    IComparable QueueName 
get; } 
}

WF中所有的通信的活动都实现了这个接口。

QueueName 属性必须返回 IComparable 值,消息加入队列时,它可以唯一地标识您的活动。对于用于将消息加入队列以通知工作流运行时的代码,也需要使用这同一个队列名。

通过此接口,能够命令活动在其执行前订阅事件并让活动知道何时取消订阅。在订阅和取消订阅方法中,该活动负责确保使用 QueueName 来创建队列并在处理结束时删除队列。此外,这也为您的活动能够向任何本地服务注册信息提供了机会,这些本地服务将代表活动来执行逻辑并通过将消息加入队列予以响应。

本地服务是您定义并从主机添加到工作流运行时的一个类,它可以被您的宿主代码、工作流或您的活动所利用。只要宿主应用程序处于运行状态,本地服务就能够维护事件处理程序或其他侦听程序,从而可通过将消息加入队列来确保相应的数据到达工作流。您传递给本地服务的信息应包括队列名和工作流实例 ID 的相关信息,以及该服务发起工作或向您的活动返回结果时所需的任何信息。

1.下面我们先来实现一个这样的自定义活动,利用该活动得到对列中的信息,然后在将该信息发送给宿主程序代码如下:

 

RequestResponseData.cs
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->using System; 
using System.ComponentModel; 
using System.ComponentModel.Design; 
using System.Collections; 
using System.Drawing; 
using System.Linq; 
using System.Workflow.ComponentModel; 
using System.Workflow.ComponentModel.Design; 
using System.Workflow.ComponentModel.Compiler; 
using System.Workflow.ComponentModel.Serialization; 
using System.Workflow.Runtime; 
using System.Workflow.Activities; 
using System.Workflow.Activities.Rules; 
using System.Collections.Generic; 

namespace CaryQueue 

    [Designer(
typeof(SequentialActivityDesigner),typeof(IDesigner))] 
    
public partial class RequestResponseData: SequenceActivity,IActivityEventListener<QueueEventArgs>,IEventActivity 
    

        
public RequestResponseData() 
        

            InitializeComponent(); 
        }
 

        
Properties#region Properties 

        
public static DependencyProperty OutputValuesProperty = System.Workflow.ComponentModel.DependencyProperty.Register("OutputValues"typeof(Dictionary<stringstring>), typeof(RequestResponseData)); 

        [Description(
"The values to be sent back to the host")] 
        [Category(
"Data")] 
        [Browsable(
true)] 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] 
        
public Dictionary<stringstring> OutputValues 
        

            
get 
            

                
return ((Dictionary<stringstring>)(base.GetValue(RequestResponseData.OutputValuesProperty))); 
            }
 
            
set 
            

                
base.SetValue(RequestResponseData.OutputValuesProperty, value); 
            }
 
        }
 
        
public static DependencyProperty InputValuesProperty = System.Workflow.ComponentModel.DependencyProperty.Register("InputValues"typeof(Dictionary<stringstring>), typeof(RequestResponseData)); 

        [Description(
"The data sent to the activity")] 
        [Category(
"Data")] 
        [Browsable(
true)] 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] 
        
public Dictionary<stringstring> InputValues 
        

            
get 
            

                
return ((Dictionary<stringstring>)(base.GetValue(RequestResponseData.InputValuesProperty))); 
            }
 
            
set 
            

                
base.SetValue(RequestResponseData.InputValuesProperty, value); 
            }
 
        }
 

        
#endregion
 

        
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) 
        


            
if (ProcessMessage(GetQueue(executionContext, QueueName))) 
            

                
//let the base class run the children, and return status 
                return base.Execute(executionContext); 
            }
 
            
//if no items are there, then subscribe to get notified when they arrive 
            Subscribe(executionContext, this); 
            
return ActivityExecutionStatus.Executing; 
        }
 

        
IEvent and IActivityListener#region IEvent and IActivityListener 

        [Browsable(
false)] 
        
public IComparable QueueName 
        

            
get return "CaryQueue"; } 
        }
 

        
public void Subscribe(ActivityExecutionContext parentContext, IActivityEventListener<QueueEventArgs> parentEventHandler) 
        

            WorkflowQueue queue 
= parentContext.GetService<WorkflowQueuingService>().CreateWorkflowQueue(QueueName, false); 
            queue.RegisterForQueueItemAvailable(parentEventHandler); 

        }
 

        
public void Unsubscribe(ActivityExecutionContext parentContext, IActivityEventListener<QueueEventArgs> parentEventHandler) 
        

            WorkflowQueue q 
= GetQueue(parentContext, QueueName); 
            
if (q != null
            

                q.UnregisterForQueueItemAvailable(parentEventHandler); 
                parentContext.GetService
<WorkflowQueuingService>().DeleteWorkflowQueue(QueueName); 
            }
 
        }
 

        
public void OnEvent(object sender, QueueEventArgs e) 
        

            ActivityExecutionContext ctx 
= sender as ActivityExecutionContext; 

            
if (ProcessMessage(GetQueue(ctx, e.QueueName))) 
            

                
if (base.Execute(ctx) == ActivityExecutionStatus.Closed) 
                    ctx.CloseActivity(); 
            }
 
        }
 

        
#endregion
 

        
private WorkflowQueue GetQueue(ActivityExecutionContext context, IComparable queueName) 
        

            WorkflowQueuingService qService 
= context.GetService<WorkflowQueuingService>(); 
            
if (qService != null && qService.Exists(queueName)) 
                
return qService.GetWorkflowQueue(queueName); 
            
else 
                
return null
        }
 

        
private bool ProcessMessage(WorkflowQueue queue) 
        

            
if (queue == null || queue.Count == 0
                
return false

            MessageHelper msg 
= queue.Peek() as MessageHelper; 
            
if (msg != null && msg.InputValues != null
            

                InputValues 
= msg.InputValues; 
                Console.WriteLine(
"Request:"+msg.InputValues["inputvalueone"]); 
                Console.WriteLine(
"Request:" + msg.InputValues["inputvaluetwo"]); 
                
return true
            }
 

            
return false
        }
 

        
/**//// <summary> 
        
/// Called when the base class completes executing the 
        
/// child activities. Here we know all the children are complete. 
        
/// </summary> 
        
/// <param name="executionContext"></param> 

        protected override void OnSequenceComplete(ActivityExecutionContext executionContext) 
        

            
//pull the message from the queue and send the 
            
//response back to the host, signalling we are done. 
            WorkflowQueue q = executionContext.GetService<WorkflowQueuingService>().GetWorkflowQueue(QueueName); 
            MessageHelper msg 
= q.Dequeue() as MessageHelper; 
            msg.SendResponse(OutputValues); 

            
//clean up, we
分享到:
评论

相关推荐

    坚持学习WF,WF学习教程

    坚持学习WF(11):工作流通信与队列 WF 提供的通信模型是构建于队列系统的基础之上,我们可以使用自定义活动来注册以接收关于队列的消息,而宿主应用程序中的服务则发送关于队列的消息。自定义活动可以使用此模型来...

    坚持学习WF

    坚持学习WF(11):工作流通信与队列 WF 提供的通信模型是构建于队列系统的基础之上,我们可以使用自定义活动来注册以接收关于队列的消息,而宿主应用程序中的服务则发送关于队列的消息。自定义活动可以使用此模型来...

    wf工作流资料<转自网上的笔记>

    "坚持学习WF(11)工作流通信与队列"关注WF如何与其他组件或服务进行通信,可能包括使用队列进行异步通信的场景。 "坚持学习WF(12)使用EventHandlingScopeActivity活动"更进一步,专门讲解EventHandlingScopeActivity...

    如何集成wcf工作流服务和服务总线队列

    将WCF工作流服务与服务总线队列集成,可以创建高效、可扩展的应用系统。下面将详细阐述这一集成过程中的主要知识点。 1. **WCF工作流服务**:WCF WorkFlow Service(WF)是.NET Framework的一部分,允许开发人员...

    WF_WCF_Samples.rar

    5. **工作流服务**:使用WF创建WCF服务,结合了流程管理和分布式通信的能力。 Windows Communication Foundation(WCF)是.NET Framework的另一重要组件,用于构建高度可配置的、安全的、可靠的、可扩展的分布式...

    WCF_WF_Sample微软官方例子

    6. **工作流服务:** 将WF与WCF结合,创建基于工作流的服务。 **通过WCF_WF_Samples.exe这个压缩包,开发者可以下载并运行这些官方示例,逐步学习和实践WCF和WF的用法。每个示例通常会包含完整的代码、详细的文档和...

    Apress.Pro.WF.Windows.Workflow.in.dot.NET.3.5.Jun.2008

    - **增强的工作流设计器**: .NET 3.5 中的 WF 引入了一个更加直观且功能强大的工作流设计器,使得开发者可以更轻松地构建复杂的流程图。 - **更好的性能优化**: 相较于之前的版本,.NET 3.5 中的 WF 在性能方面有了...

    .NET3.0学习资料大全

    4. WF工作流:学习工作流的生命周期,包括设计、实例化、执行和跟踪。理解活动、工作流持久化以及如何将工作流集成到实际应用中。 5. Linq和linq-to-sql:学习如何使用Linq进行数据查询,以及如何利用linq-to-sql将...

    《精通C# 5.0与.NET 4.5高级编程——LINQ、WCF、WPF和WF

    Windows Workflow Foundation (WF)则是.NET Framework中的工作流引擎,它允许开发者以模型驱动的方式来实现业务流程。WF提供了一套强大的工具和技术,可以创建、执行和管理复杂的业务流程,包括顺序流程、状态机流程...

    WCF+WF+SilverLight培训实例

    通常,这样的图会展示各个组件之间的关系,包括WCF服务、WF工作流逻辑以及Silverlight客户端如何相互作用。可能包括数据流、服务接口、工作流状态转换以及用户界面交互等方面的设计。 在学习和实践中,了解如何利用...

    精通C# 3.0与.NET 3.5高级编程——LINQ、WCF、WPF、WF 源代码

    5. WF(Windows Workflow Foundation):WF为.NET Framework提供工作流支持,允许开发者在应用程序中实现复杂的业务流程。WF定义了工作流的生命周期,包括设计、执行、暂停、恢复和终止等状态。通过WF,开发者可以...

    精通c# 5.0与.net 4.5高级编程 PDF文件和源代码

    WF与.NET 4.5的集成使得工作流的创建和管理变得更加简单。 总的来说,这本书全面覆盖了.NET开发的关键技术,无论是对于初学者还是经验丰富的开发者,都能从中获益匪浅。通过学习书中的实例和代码,读者将能够熟练...

    Wrox.Professional.Visual.Basic.2010.and.NET.4

    - 工作流设计与实现 - 活动与状态机 - 故障恢复与事务 **章节27:本地化** - **知识点**: - 多语言支持 - 资源文件与字符串资源 - 格式化与排序 - 文化敏感度 **章节28:COM 互操作** - **知识点**: -...

    Professional Visual Basic 2010 and .NET 4

    - **实现工作流**: 如何使用WF实现复杂的工作流逻辑。 - **本地化** (第27章): - **国际化与本地化**: 国际化(Internationalization)与本地化(Localization)的区别。 - **资源文件**: 如何使用资源文件进行本地...

    Windows Server AppFabric Architecture

    - **AppFabric工作流管理服务**:工作流服务与WF集成,使得业务流程能够被定义、执行和监控,增强了业务逻辑的灵活性。 **数据存储**:AppFabric使用内存缓存来提高数据访问速度,同时也支持将数据持久化到数据库中...

    WCF4高级编程Professional.WCF.4

    11. **WF4集成**:结合Windows Workflow Foundation (WF4),创建工作流驱动的服务,实现更复杂的业务逻辑。 12. **服务代理生成**:理解如何使用svcutil工具生成客户端代理类,以及如何在项目中引用和使用这些代理...

    Pro Windows Server AppFabric 2010.pdf

    - **集成优势:** 通过AppFabric,WCF服务可以轻松地与其他WF工作流或其他组件集成,从而构建出高度集成和灵活的分布式系统。 **4. 部署与托管策略** - **缓存服务:** AppFabric提供了一个高性能的分布式内存缓存...

    WCF .net development 教程

    - 深入研究高级主题,如消息队列、工作流服务(WF)和持久性会话。 在22155448295.pdf文档中,你可能会找到关于这些知识点的详细讲解,包括实例代码、配置示例和最佳实践。通过深入学习和实践,你将能够熟练掌握WCF...

Global site tag (gtag.js) - Google Analytics