WF中提供了很多内置的服务,其中工作流计划服务是用来管理工作流实例线程的。默认情况下WF会自动使用DefaultWorkflowSchedulerService服务。使用该服务时在工作流运行时引擎上以异步方式运行工作流实例的线程。 等待运行的工作流存储在 DefaultWorkflowSchedulerService 的内部队列中.当 DefaultWorkflowSchedulerService 要启动工作流时,从 .NET Framework 线程池中获取一个线程并使用此线程运行工作流。 MaxSimultaneousWorkflows 属性确定调度程序服务同一时间允许的并发线程数。 例如,如果限值为 4,则 DefaultWorkflowSchedulerService 将从 .NET Framework 线程池中最多获取 4 个线程来执行工作流。 如果已经运行 4 个工作流,则其他工作项(工作流)将放入队列中,最终在线程可用时执行。
除了使用WF默认提供的,我们还可以手动去加载ManualWorkflowSchedulerService服务。它提供了一个线程服务,该服务允许创建工作流实例的宿主应用程序指定用于运行工作流实例的 Thread。 使用此线程服务,宿主应用程序可在单个 Thread 上运行一个工作流实例(即处于同步模式)。 此模式将阻止宿主应用程序的执行,直到工作流实例进入空闲状态。 随后,只能通过使用此服务的 RunWorkflow 方法执行工作流实例。
下面我们通过MSDN中的一个例子来说明工作流中的线程以及如何使用DefaultWorkflowSchedulerService和ManualWorkflowSchedulerService服务。
一:在该实例中首先开发一个自定义活动WaitForMessageActivity.cs,代码如下:
using System; using System.ComponentModel; using System.Threading; using System.Workflow.Activities; using System.Workflow.ComponentModel; using System.Workflow.ComponentModel.Design; using System.Workflow.Runtime; namespace Microsoft.Samples.Workflow.WorkflowThreading {
[ToolboxItem(typeof(ActivityToolboxItem))]
public partial class WaitForMessageActivity: Activity
{
WorkflowQueue workflowQueue;
public WaitForMessageActivity()
{
InitializeComponent();
}
protected override void Initialize(IServiceProvider provider)
{
ThreadMonitor.WriteToConsole(Thread.CurrentThread, "WaitForMessageActivity",
"WaitForMessageActivity执行构造函数");
WorkflowQueuingService queuingService = (WorkflowQueuingService)provider.
GetService(typeof(WorkflowQueuingService));
this.workflowQueue = queuingService.CreateWorkflowQueue(
"WaitForMessageActivityQueue", false);
this.workflowQueue.QueueItemAvailable += this.HandleExternalEvent;
}
private void HandleExternalEvent(Object sender, QueueEventArgs args)
{
ThreadMonitor.WriteToConsole(Thread.CurrentThread, "WaitForMessageActivity",
"WaitForMessageActivity外部事件处理程序");
object data = this.workflowQueue.Dequeue();
ActivityExecutionContext context = sender as ActivityExecutionContext;
context.CloseActivity();
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext context)
{
ThreadMonitor.WriteToConsole(Thread.CurrentThread, "WaitForMessageActivity",
"WaitForMessageActivity等待外部事件处理程序");
return ActivityExecutionStatus.Executing;
}
}
}
二:工作流设计如下图:
DelayActivity对工作流的影响我们在前面的文章中有过说明,我们就不管这个了。工作流的代码如下:
using System; using System.ComponentModel; using System.Workflow.Activities; using System.Threading; namespace Microsoft.Samples.Workflow.WorkflowThreading { public sealed partial class ThreadingWorkflow : SequentialWorkflowActivity { private string branchFlag; public ThreadingWorkflow() { InitializeComponent(); ThreadMonitor.WriteToConsole(Thread.CurrentThread, "ThreadingWorkflow",
"ThreadingWorkflow: 执行构造函数"); } public string BranchFlag { get { return this.branchFlag;} set { this.branchFlag = value;} } private void OnCodeActivity1ExecuteCode(object sender, EventArgs e) { ThreadMonitor.WriteToConsole(Thread.CurrentThread, "ThreadingWorkflow",
"CodeActivity1的事件处理程序"); } private void OnCodeActivity2ExecuteCode(object sender, EventArgs e) { ThreadMonitor.WriteToConsole(Thread.CurrentThread, "ThreadingWorkflow",
"CodeActivity2的事件处理程序"); } private void OnCodeActivity3ExecuteCode(object sender, EventArgs e) { ThreadMonitor.WriteToConsole(Thread.CurrentThread, "ThreadingWorkflow",
"CodeActivity3的事件处理程序"); } private void IfElseBranchActivityCodeCondition(object sender, ConditionalEventArgs e) { e.Result = !this.BranchFlag.Equals("Delay", StringComparison.OrdinalIgnoreCase); } } }
三:宿主程序代码如下:
using System; using System.Collections.Generic; using System.Threading; using System.Workflow.Runtime; using System.Workflow.Runtime.Hosting; using System.Drawing; namespace Microsoft.Samples.Workflow.WorkflowThreading { class Program { static AutoResetEvent waitHandle = new AutoResetEvent(false); static AutoResetEvent readyHandle = new AutoResetEvent(false); static WorkflowInstance workflowInstance; static WorkflowRuntime workflowRuntime; static void Main(string[] args) { if (args.Length < 2) { Console.WriteLine("使用该形式命令行WorkflowThreading.exe [Single | Multi]
[Delay | WaitForMessage]"); return; } if (!args[0].Equals("Single", StringComparison.OrdinalIgnoreCase) &&
!args[0].Equals("Multi", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("指定Single 或者Multi 作为第一个命令行参数"); return; } if (!args[1].Equals("Delay", StringComparison.OrdinalIgnoreCase) &&
!args[1].Equals("WaitForMessage", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("指定Delay 或者WaitForMessage 作为第二个命令行参数"); return; } ThreadMonitor.Enlist(Thread.CurrentThread, "主机"); Console.ForegroundColor = ConsoleColor.White; using (workflowRuntime = new WorkflowRuntime()) { ManualWorkflowSchedulerService scheduler = null; if (args[0].ToString().Equals("Single", StringComparison.OrdinalIgnoreCase)) { scheduler = new ManualWorkflowSchedulerService(); workflowRuntime.AddService(scheduler); } workflowRuntime.StartRuntime(); workflowRuntime.WorkflowCompleted += OnWorkflowCompleted; workflowRuntime.WorkflowTerminated += OnWorkflowTerminated; workflowRuntime.WorkflowIdled += OnWorkflowIdled; workflowRuntime.WorkflowCreated += OnWorkflowCreated; Type type = typeof(ThreadingWorkflow); Dictionary<string, object> workflowParameters = new Dictionary<string, object>(); workflowParameters.Add("BranchFlag", args[1]); Console.WriteLine("\n--- 开始工作流之前---\n"); workflowInstance = workflowRuntime.CreateWorkflow(type, workflowParameters); workflowInstance.Start(); Console.WriteLine("\n--- 开始工作流之后---\n"); if (scheduler != null) scheduler.RunWorkflow(workflowInstance.InstanceId); readyHandle.WaitOne(); if (args[1].Equals("WaitForMessage", StringComparison.OrdinalIgnoreCase)) { workflowInstance.EnqueueItem("WaitForMessageActivityQueue", "Hello",
null, null); } if (scheduler != null) scheduler.RunWorkflow(workflowInstance.InstanceId); waitHandle.WaitOne(); workflowRuntime.StopRuntime(); } } static void OnWorkflowCreated(object sender, WorkflowEventArgs e) { ThreadMonitor.WriteToConsole(Thread.CurrentThread, "Host",
"Host: Processed WorkflowCreated Event"); } static void OnWorkflowIdled(object sender, WorkflowEventArgs e) { if (workflowRuntime.GetService<ManualWorkflowSchedulerService>() != null) SetReloadWorkflowTimer(); else readyHandle.Set(); ThreadMonitor.WriteToConsole(Thread.CurrentThread, "Host",
"Host: Processed WorkflowIdle Event"); Console.WriteLine("\n--- 工作流空闲---\n"); } static void SetReloadWorkflowTimer() { DateTime reloadTime = workflowInstance.GetWorkflowNextTimerExpiration(); if (reloadTime == DateTime.MaxValue) { readyHandle.Set(); } else { TimeSpan timeDifference = reloadTime - DateTime.UtcNow + new TimeSpan(0, 0, 0, 0, 1); Timer timer = new System.Threading.Timer( new TimerCallback(ReloadWorkflow), null,timeDifference < TimeSpan.Zero ? TimeSpan.Zero : timeDifference, new TimeSpan(-1)); } } static void ReloadWorkflow(object state) { if (workflowInstance.GetWorkflowNextTimerExpiration() > DateTime.UtcNow) SetReloadWorkflowTimer(); else readyHandle.Set(); } static void OnWorkflowCompleted(object sender, WorkflowCompletedEventArgs e) { ThreadMonitor.WriteToConsole(Thread.CurrentThread, "Host",
"Host: Processed WorkflowCompleted Event"); waitHandle.Set(); Console.WriteLine("\n--- 工作流完成---\n"); } static void OnWorkflowTerminated(object sender, WorkflowTerminatedEventArgs e) { Console.WriteLine(e.Exception.Message); waitHandle.Set(); } } }
在宿主程序我们根据命令行参数的不同来决定是否加载ManualWorkflowSchedulerService ,如果加载了该服务我们
调用该类的RunWorkflow方法来运行工作流实例。
四:ThreadMonitor类的用途是用不同的颜色为每个线程的输出着色。代码如下:
using System; using System.Threading; using System.Collections.Generic; using System.Text; namespace Microsoft.Samples.Workflow.WorkflowThreading { public static class ThreadMonitor { private static int threadCount; private static Dictionary<string, ConsoleColor> threadList = new
Dictionary<string, ConsoleColor>(); public static void Enlist(Thread thread, string instanceName) { if ((thread.Name == null) || (thread.Name.Length == 0)) { thread.Name = string.Format("{0} 线程[{1}]", instanceName, threadCount++); if (!threadList.ContainsKey(thread.Name)) threadList.Add(thread.Name, GetConsoleColor()); } } public static void WriteToConsole(Thread thread, string instanceName, string message) { Enlist(thread, instanceName); WriteToConsole(thread, message); } public static void WriteToConsole(Thread thread, string message) { if (threadList.ContainsKey(thread.Name)) Console.ForegroundColor = threadList[thread.Name]; Console.WriteLine("{0} --> {1}", thread.Name, message); } private static ConsoleColor GetConsoleColor() { if ((int)Console.ForegroundColor < 9) return ConsoleColor.White; else return (ConsoleColor)(int)Console.ForegroundColor - 1; } } }
五:下图是执行的结果对比,我们可以清晰的看到线程的变化情况。
发表评论
-
平淡的2007
2007-12-24 08:04 817早上起来,送女朋友去公交车站,然后回来赶紧打开电脑,先 ... -
DreamSpark发布,高校学生免费使用Visual Studio 2008 Professional Edition 等微软软件
2008-02-20 13:23 1415今天上网无意中搜索到学生可以免费使用VS2008专业版,后来又 ... -
坚持学习WF(1):从HelloWorld开始
2008-04-04 16:30 892[置顶]坚持学习WF文章索 ... -
坚持学习WF(2):WF创作模式和设计时工具
2008-04-05 17:19 639[置顶]坚持学习WF文章索 ... -
坚持学习WF(3):WF框架概览
2008-04-08 07:27 783[置顶]坚持学习WF文章索 ... -
坚持学习WF(4):活动(Activity)和依赖属性(DependencyProperty)
2008-04-12 00:01 1148[置顶]坚持学习WF文章索引 活动(Activity) 活动 ... -
坚持学习WF(5):自定义活动(CustomActivity)
2008-04-13 15:25 929当WF提供的标准活动不能满足我们的需求的时候,我们就需要定义自 ... -
MOSS点滴(1):如何开发和部署feature
2008-04-16 21:35 835Features 是MOSS 2007以开箱即用的一套新功能, ... -
MOSS点滴(2):自定义Application Page
2008-04-19 20:07 844在MOSS中后台管理的页面都是Application Pag ... -
坚持学习WF(6):开发可复用的宿主程序
2008-04-21 21:45 695我们之前写工作流宿主 ... -
MOSS点滴(3):说说MOSS中的母版页
2008-04-25 21:15 1187MOSS中有两种页面:Site P ... -
MOSS点滴(4):实现Form认证
2008-04-29 21:12 705本文主要参考了网上的一些文章,但有些文章有些地方说的不是很明确 ... -
坚持学习WF(7):流程控制(Flow Control)
2008-04-30 18:10 839本文主要说说WF中和流 ... -
坚持学习WF(8):本地服务之调用外部方法
2008-05-09 08:17 761WF提供了一组核心服务 ... -
MOSS中的WebPart开发
2008-05-10 13:53 1060由于在asp.net1.1的时候asp.net中还没有webp ... -
坚持学习WF(9):本地服务之事件处理
2008-05-28 07:49 800[置顶]坚持学习WF文章索引 一:先来介绍两个活动 Even ... -
坚持学习WF(10):在工作流中使用关联
2008-06-01 13:03 692[置顶]坚持学习WF文章索 ... -
坚持学习WF(11):工作流通信与队列
2008-06-07 15:45 735[置顶]坚持学习WF文章索引 WF 提供的通信模型是构建于 ... -
MOSS中创建自定义内容类型
2008-06-12 20:23 1106一:简要介绍 某类内容 ... -
.NET中IDisposable接口的基本使用
2008-06-15 12:01 950首先来看MSDN中关于这个接口的说明: [ComVisible ...
相关推荐
坚持学习WF(19):工作流线程 WF中提供了很多内置的服务,其中工作流计划服务是用来管理工作流实例线程的。默认情况下WF会自动使用DefaultWorkflowSchedulerService服务,我们还可以手动去加载...
坚持学习WF(19):工作流线程 WF中提供了很多内置的服务,其中工作流计划服务是用来管理工作流实例线程的。默认情况下WF会自动使用DefaultWorkflowSchedulerService服务,我们还可以手动去加载...
最后,"坚持学习WF(19)工作流线程"涵盖了WF中的并发和多线程概念,这对于理解和优化工作流性能至关重要。 总的来说,这个压缩包提供了一条从基础到进阶的WF学习路径,涵盖了WF的核心概念、设计工具、自定义活动、...
- **实现工作流**: 如何使用WF实现复杂的工作流逻辑。 - **本地化** (第27章): - **国际化与本地化**: 国际化(Internationalization)与本地化(Localization)的区别。 - **资源文件**: 如何使用资源文件进行本地...
- 第33章:Windows工作流基础(WF) - 第34章:客户端应用程序服务 - 第35章:同步服务 - 第36章:WCF RIA服务 #### 第八部分:配置和资源 (Configuration and Resources) - 第37章:配置文件 - 第38章:连接字符串...
23. **WF(Windows Workflow Foundation)**:处理工作流逻辑。 ### C#新特性 24. **匿名类型**:在不需要明确命名类型的情况下创建对象。 25. **Lambda表达式**:简化短小的委托定义,常用于LINQ查询。 26. **匿名...
- 工作流设计与实现 - 活动与状态机 - 故障恢复与事务 **章节27:本地化** - **知识点**: - 多语言支持 - 资源文件与字符串资源 - 格式化与排序 - 文化敏感度 **章节28:COM 互操作** - **知识点**: -...
- WF(Windows Workflow Foundation):流程编程和工作流服务的应用。 5. **框架进阶** - ASP.NET MVC:模型-视图-控制器架构,路由、过滤器和 Areas 的使用。 - Entity Framework:ORM(Object-Relational ...
- 介绍了WF(Windows Workflow Foundation)的基础知识,包括工作流设计和执行模型。 - 讨论了如何使用WF构建业务流程自动化应用程序。 #### 总结 本书《Beginning Visual C# 2010》是一本全面而深入的C#编程...
Ch_18 Code可能与.NET 3.0的Windows Workflow Foundation (WF)有关,这是一个用于创建工作流应用程序的平台。这部分可能会展示如何定义、执行和管理业务流程。 Ch_19 Code可能涵盖C#的高级特性,如匿名方法、lambda...