WF学习笔记4-持久化(加载卸载实例)

by Ryan 27. August 2009 17:22

 

事实上,我们在实际应用中的WF,都很难以在几秒钟乃至几分钟内运行完成,很多时候,运行周期可能会长达数天数月,比如一个订单处理工作流。这个时候,让线程在内存中挂起如此长的时间,是不现实的,第一是占用系统资源,第二是如果中途遇到系统重启等故障,则会造成数据丢失的风险。

因此,WF需要提供一种能让状态持久化的机制。在运行长时间任务时,能让工作流暂时脱机。WF提供了一个工作流持久化的服务:SqlWorkflowPersistenceService,它用来把工作流实例序列化进SQL SERVER数据库。

 

WorkflowInstance提供了三个方法用来执行持久化。分别是:

Load:加载先前被持久化的实例

Unload:从内存中卸载(持久化)该工作流实例,该方法会阻塞当前线程,直到该工作流实例被真正卸载,这可以是一个漫长的过程。

TryUnload:从内存中卸载(持久化)该工作流实例,该方法不会阻塞当前线程,不管工作流实例被卸载与否,都会立即返回。

 

下面以一个示例来说明实现WF持久化的详细步骤:

 

创建SQL SERVER数据库以进行持久化

首先在SQL SERVER 2008中创建一个新的数据库,名称为:WorkflowStore

然后在路径:C:\WINDOWS\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\ZH-CHS中找到SqlPersistenceService_Schema.sqlSqlPersistenceService_Logic.sql。在数据库WorkflowStore中运行这这段脚本。脚本会创建SqlWorkflowPersistenceService需要用到的数据表以及存储过程。

 

创建宿主应用程序

1、打开VS2008,创建一个WINDOWS应用程序。名称为APJ.WF.WorkflowPersister

 

 

1

 

2、在项目中添加应用程序配置文件app.config。在app.config中加入数据库连接字符串。如下所示:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <connectionStrings>

    <add name="StorageDatabase" connectionString="Data Source=apj092;Initial Catalog=WorkflowStore;Integrated Security=True;"/>

  </connectionStrings>

</configuration>

 

3、打开Form1.cs切换到WINDOWS Forms试图设计器。在窗体上放入三个按钮,分别更改显示的名称如下图所示:

 

  

 

 

 

2

 

4、于是我们就为测试工作流加载卸载准备好了界面。接下来我们准备一个顺序工作流。在解决方案中新建一个顺序工作六库,名称为:APJ.WF.PersistedWorkflow

 

3

 

5、在Workflow1.cs中顺序加入两个Code活动。如下图:

 

 

4

 

6、分别修改其ExcuteCode代码为:

private void PreUnload(object sender, EventArgs e)

        {

            _started = DateTime.Now;

            System.Diagnostics.Trace.WriteLine(String.Format("*** Workflow {0} started: {1}",

            WorkflowInstanceId.ToString(),

            _started.ToString("MM/dd/yyyy hh:mm:ss.fff")));

            System.Threading.Thread.Sleep(10000); // 10 seconds

        }

 

        private void PostUnload(object sender, EventArgs e)

        {

            DateTime ended = DateTime.Now;

            TimeSpan duration = ended.Subtract(_started);

            System.Diagnostics.Trace.WriteLine(

                String.Format("*** Workflow {0} completed: {1}, duration: {2}",

                    WorkflowInstanceId.ToString(),

                    ended.ToString("MM/dd/yyyy hh:mm:ss.fff"),

                    duration.ToString()

                    )

                );

        }

 

7、再回到宿主程序,Windows Form应用程序。在应用里添加该工作流项目的引用。为Form1.cs类添加两个全局的似有变量_runtime_instance 分别为WF运行时对象和WF实例对象。在Form1_Load事件中添加如下代码,初始化此二对象。其中用到的部分类和方法我们将在后面添加。

 

_runtime = WorkflowFactory.GetWorkflowRuntime();

            _runtime.WorkflowCompleted +=

            new EventHandler<WorkflowCompletedEventArgs>(Runtime_WorkflowCompleted);

            _runtime.WorkflowTerminated +=

            new EventHandler<WorkflowTerminatedEventArgs>(Runtime_WorkflowTerminated);

 

8、分别修改三个buttonClick代码为如下所示:

 

private void button1_Click(object sender, EventArgs e)

        {

            button2.Enabled = true;

            button1.Enabled = false;

            _instance = _runtime.CreateWorkflow(typeof(PersistedWorkflow.Workflow1));

            _instance.Start();

        }

 

        private void button2_Click(object sender, EventArgs e)

        {

            button2.Enabled = false;

            try

            {

                _instance.Unload();

                button3.Enabled = true;

            } // try

            catch (Exception ex)

            {

                MessageBox.Show(String.Format("Exception while unloading workflow" +

                " instance: '{0}'", ex.Message));

            } // catch123

        }

 

        private void button3_Click(object sender, EventArgs e)

        {

            button3.Enabled = false;

            try

            {

                _instance.Load();

            } // try

            catch (Exception ex)

            {

                MessageBox.Show(String.Format("Exception while loading workflow" +

                " instance: '{0}'", ex.Message));

            } // catch

            button1.Enabled = true;

        }

 

此三个button的作用为控制工作流的启动,卸载和加载。

9、在Form1.cs的类的末尾加入如下代码:

void Runtime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)

        {

            WorkflowCompleted();

        }

        void Runtime_WorkflowTerminated(object sender, WorkflowTerminatedEventArgs e)

        {

            WorkflowCompleted();

        }

 

        private delegate void WorkflowCompletedDelegate();

        private void WorkflowCompleted()

        {

            if (this.InvokeRequired)

            {

                // Wrong thread, so switch to the UI thread  

                WorkflowCompletedDelegate d = delegate() { WorkflowCompleted(); };

                this.Invoke(d);

            } // if  

            else

            {

                button1.Enabled = true;

                button2.Enabled = false;

                button3.Enabled = false;

            } // else  

        }

 

10、在项目中添加WF工厂类,取名为:WorkflowFactory此类的作用为使用工厂和单例模式提供一个唯一的WF的运行时对象。具体代码如下:

class WorkflowFactory

    {

        //workflow runtime的单一实例

        private static WorkflowRuntime _workflowRuntime = null;

        //private static object _syncRoot = new object();

        //工厂方法

        public static WorkflowRuntime GetWorkflowRuntime()

        {

            if (null == _workflowRuntime)

            {

                AppDomain.CurrentDomain.ProcessExit += new EventHandler(StopWorkflowRuntime);

                AppDomain.CurrentDomain.DomainUnload += new EventHandler(StopWorkflowRuntime);

                _workflowRuntime = new WorkflowRuntime();

                string conn = ConfigurationManager.ConnectionStrings["StorageDatabase"].ConnectionString;

                _workflowRuntime.AddService(new SqlWorkflowPersistenceService(conn));

                _workflowRuntime.StartRuntime();

            }

            return _workflowRuntime;

        }

        static void StopWorkflowRuntime(object sender, EventArgs e)

        {

            if (_workflowRuntime != null)

            {

                if (_workflowRuntime.IsStarted)

                {

                    try

                    {

                        _workflowRuntime.StopRuntime();

                    }

                    catch (ObjectDisposedException)

                    {

                    }

                }

            }

        }

    }

 

 

现在整个示例就做好了。全部代码在本文的末尾提供下载。我们按F5运行,可以看到如下的效果:

 

 

5

点击Start WF之后,在10秒内点击Unload WF ,一阵无响应(少于10秒)之后,可以在数据库中打开InstanceState表,可以看到这样一条记录。可见,此工作流已经被持久化到数据库中了。 

 

6

在适当的时候,又可以通过重新加载此工作流,恢复WF的状态。

 

全部代码点击此处下载。

APJ.WF.WorkflowPersister.rar (59.29 kb)

 

Tags: , ,

技术文章

成都印象

by Ryan 22. August 2009 11:50
    很显然,这不是一篇技术文章。作为一名来自四川的同事,谨以此文把四川,把成都推荐给大家,如果你有旅行计划的话,成都算是一个不错的目的地。 
    我是四川人,但不是成都人,所以对于成都来说,我仍然是外地人,因此我能够以一个外地人的身份客观的评价这座城市。从大学毕业开始直到来APJ以前,一直在成都工作生活,算算时间,整整有5年了。 五年,足可以评头论足一番了吧。呵呵。
 
 
千年历史文化古都
 
    关于成都的历史,谷歌一下之后可以看到,成都建城于公元前311年,是中国城址未变,延续至今最古老的城市之一,仅次于苏州(建于公元前514年)。因五代时遍种芙蓉,汉时织锦业发达,故别称“蓉城”或“锦城”。
    这里有,一代名相诸葛亮的祠堂--武侯祠;诗圣杜甫曾居住之所--杜甫草堂;伟大的水利工程--都江堰。这里还有青羊宫、文殊院、昭觉寺、锦里、琴台路、大慈寺、宽窄巷子、永陵等历史文化古迹。  这就不啰嗦了,总之一句话,好玩的地方不少。
 
 
食色之城
 
    我承认,我本是俗人。不过,食色性也,这原是出自圣贤之口。
    色·成都
    成都地处西南边陲,自古就不在群雄逐鹿的“中原”之列,然而,居于一隅的成都却从未偏安一隅,古老的成都永远焕发着年轻的活力,众所周知,成都的美女是出了名的。一位著名主持人曾说过,“成都的每两个电线杆之间就有3个美女出没。”(我绝对相信这句话的可信度,因为现如今成都的大部分电网都在地下,要找到两个电线杆,这距离就长了。呵呵。)
    食·成都
    当然,这是玩笑,因为成都的美女之多是不需要证明的,正如成都的小吃闻名于世一样。龙抄手、赖汤圆、钟水饺、韩包子、夫妻肺片、麻婆豆腐、双流兔头,老妈蹄花。。。不好意思,没忍住,我擦下口水先。~_+   成都的小吃实在多不胜数,食在成都,当之无愧。  
 
The best friendly City
 
    当说到一个城市很友好的时候,常规情况下,我们会说,她不排外,对外地人充满热情,如此云云。固然,这些都是成都所具有的特质,比如当你向一个人行道上捧着茶碗的大爷问路的时候,几乎都可以得到相当热情细致的回答,有时,当你已经走出老远的距离,仍然能听到身后传来一个沙哑却不乏浑厚的嗓音:“小伙子,到前面第二个红绿灯口子左转哈”。其友好热情程度,可见一斑。
    记忆中,某次在深圳,向一个报刊亭的老板询问某某地怎么走,不说也就罢了,反而给了我一个错误的方向,于是,我就在近在眼前的目标附近很是折腾了一会,最终还是在一个做清洁的阿姨的指引下才到达目的地。诚然,我不该用一个人的言行去评价一个城市的优劣。这样太过偏执,应该以事实说话。下面就来说事实。
    又是记忆中,基本上很多城市的景区都会对当地人有很大优惠,诸如购票半价之类。不过在成都的大部分景区,你可以看到另外一种景象,那就是外地人免门票费。奇怪吧。谷歌一下“熊猫卡”就知道了,记得如果到四川去,一定要办熊猫卡哦,一般人我不告诉他。 :-)
    不知道这样,算不算Best Friendly City呢?至少我是这样认为的。
 
其他
   
    。。。
 
    国庆要到了,考虑一下去成都如何?

 

 


天府广场的毛主席像

 


春熙路


武侯祠前玩耍的孩童


川剧脸谱


锦里的草鞋铺子(刘备当年就是干这个的。。。)


锦里的一对吹唱的老人,遥想当年,子期伯牙是否如斯?


螳螂捕蝉黄雀在后,谁在拍谁? 


窄巷子


宽巷子


宽窄巷子入口,旁边还有台湾风灾募捐点。。。


长顺街的老妈蹄花,最右边红底黄字这家是最正的,24小时营业


锦里的街道


酒好不怕巷子深?


BUS站的广告牌:因为有你,成都更美好

Tags:

旅行

WF学习笔记-3-使用自定义活动

by Ryan 7. August 2009 10:34

 

上面学习了如何使用CodeActivity来定义工作流,现在我们来看看另外一种方式自定义活动。自定义活动的好处是可以复用,一旦一个自定义活动定义好之后,就可以通过拖动被多个工作流调用。

 

每个自定义活动都应该被设计成独立的组件,他们有自己的输入和输出参数,一个活动并不知道工作流中其他活动的信息,他们之间只有通过属性值来通讯。为了支持绑定,这时要采用从属属性(Dependency Properties)来代替普通的.NET属性。

 

 

第一步:

创建一个名为APJ.Workflow.Demo1的顺序工作流控制台应用程序。再在Project菜单中新建一个Activity,名称为:LoginActivity一般来说,命名应以Activity结尾。

LoginActivity用于接收用户输入的用户名和密码,然后通过该用户名和密码验证用户是否合法有效。因此,该LoginActivity至少需要这几个参数,即用户名、密码和返回结果三个。

 

我们依次添加这三个从属属性,再添加的时候有个技巧,可以通过CodeSnippet来快速添加,具体用法是,在代码的空白区点击右键,然后在弹出菜单上点击插入代码段,再依次按照下图A方式选择。最后将在光标位置自动插入一段如下图B所示的代码。

 

              图A

 

            图B

 

将其中的MyProperty改为UserId,同时修改后面的属性类型为实际需要的,这里是string不用修改。同样的,我们添加两外两个属性 UserPwdIsUserVerified。最终添加完成的这段代码应该是这样的:

 

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;

 

namespace APJ.Workflow.Demo1

{

     public partial class LoginActivity: SequenceActivity

     {

 

        public static DependencyProperty UserIdProperty = DependencyProperty.Register("UserId", typeof(string), typeof(LoginActivity));

 

        [DescriptionAttribute("UserId")]

        [CategoryAttribute("UserId Category")]

        [BrowsableAttribute(true)]

        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]

        public string UserId

        {

            get

            {

                return ((string)(base.GetValue(LoginActivity.UserIdProperty)));

            }

            set

            {

                base.SetValue(LoginActivity.UserIdProperty, value);

            }

        }

 

        public static DependencyProperty UserPwdProperty = DependencyProperty.Register("UserPwd", typeof(string), typeof(LoginActivity));

 

        [DescriptionAttribute("UserPwd")]

        [CategoryAttribute("UserPwd Category")]

        [BrowsableAttribute(true)]

        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]

        public string UserPwd

        {

            get

            {

                return ((string)(base.GetValue(LoginActivity.UserPwdProperty)));

            }

            set

            {

                base.SetValue(LoginActivity.UserPwdProperty, value);

            }

        }

 

        public static DependencyProperty IsUserVerifiedProperty = DependencyProperty.Register("IsUserVerified", typeof(bool), typeof(LoginActivity));

 

        [DescriptionAttribute("IsUserVerified")]

        [CategoryAttribute("IsUserVerified Category")]

        [BrowsableAttribute(true)]

        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]

        public bool IsUserVerified

        {

            get

            {

                return ((bool)(base.GetValue(LoginActivity.IsUserVerifiedProperty)));

            }

            set

            {

                base.SetValue(LoginActivity.IsUserVerifiedProperty, value);

            }

        }

 

         public LoginActivity()

         {

              InitializeComponent();

         }

     }

}

 

第二步:

添加了属性之后,我们需要实现该活动所要实现的业务逻辑。此操作是在Execute方法中执行的,这个方法是由基类提供的虚方法,我们需要重写该方法。在活动执行时,该方法就会被工作流同步调用。

我们这个活动是要实现验证用户帐户是否有效,因此,我们在Execute中模拟用户帐户验证的过程,实际操作中,这里大多是读取数据库,查询用户名和密码进而比对以确定是否有效,我们这里仅作实例,因此只是简单的HARDCODE一些用户信息在里面。重写Execute后的代码如下:

 

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

        {

            switch (UserId) {

                case "ryan":

                    IsUserVerified = (UserPwd == "123" ? true : false);

                    break;

                case "guest":

                    IsUserVerified = true;

                    break;

                default:

                    IsUserVerified = false;

                    break;

            }

            return base.Execute(executionContext);

        }

 

这时按F5编译一下,然后回到Workflow1的设计界面。这时可以看到左侧的工具箱中多了一个我们刚定义的那个活动。LoginActivity。如下图所示。

 

      图

C  

 

第三步:

LoginActivity拖动到Workflow1中,为了接收用户输入,我们需要为本工作流添加两个参数,用户名和用户密码,这里用普通属性即可。添加完参数之后,在转到设计界面。点击刚拖动到Workflow1中的LoginActivity活动。查看属性,可以看到开始定义的UserIdUserPwd两个属性都列在此处,点击右边的按钮,在弹出框中,将该属性绑定到Workflow1的相应属性上。

 

   图

D   

 

第四步:

再在LoginActivity的下面拖入一个IfElse活动。然后分别在两个活动的下面再拖入两个CodeActivity活动。分别为两个活动修改名字,操作完成之后的界面应该是这样的。

 

 

                       图

E    

 

第五步:

再点击IfElse活动的左侧分支,查看属性,在Condition中选择“申明性规则条件”,点击ConditionName,在弹出框中加入这样一条条件。

this.loginActivity1.IsUserVerified == True

同样的,在IfElse活动的右侧分支,在Condition中加入相应的条件。

this.loginActivity1.IsUserVerified == False

最后再在两个CodeActivity中加入一些输出代码。

        private void codeActivity1_ExecuteCode(object sender, EventArgs e)

        {

            Console.WriteLine("UserId:{0}, 登录成功!",UserId);

        }

 

        private void codeActivity2_ExecuteCode(object sender, EventArgs e)

        {

            Console.WriteLine("UserId:{0}, 用户名验证失败!",UserId);

 

        }

 

第六步:

修改program.cs中的调用代码,为WF传入参数:

 

class Program

    {

        static void Main(string[] args)

        {

            using(WorkflowRuntime workflowRuntime = new WorkflowRuntime())

            {

                AutoResetEvent waitHandle = new AutoResetEvent(false);

                workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) {waitHandle.Set();};

                workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)

                {

                    Console.WriteLine(e.Exception.Message);

                    waitHandle.Set();

                };

 

                //准备该工作流需要传入的参数,参数放置在一个Dictionary对象中

                Dictionary<string, object> wfArgs = new Dictionary<string, object>();

                wfArgs.Add("UserId", "Ryan");

                wfArgs.Add("UserPwd", "123");

 

                WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(APJ.Workflow.Demo1.Workflow1),wfArgs);

                instance.Start();

 

                //阻止当前线程,以等待异步调用的工作流完成

                waitHandle.WaitOne();

 

                //等待用户响应退出

                Console.WriteLine("Press Enter to exit");

                Console.ReadLine();

 

            }

        }

    }

 

现在就可以按F5执行了。在后面可以下载该示例的全部代码。 

APJ.Workflow.Demo1.rar (28.82 kb)

 

Tags:

技术文章

WF学习笔记-2-向你的Workflow传递参数

by Ryan 31. July 2009 10:21
初次学习WF,如有不妥或错误之处,欢迎批评指正。
打开昨天设计的APJ.Workflow.HelloApj。如果没有的话,可以点击本文末尾的链接下载源代码。
 
第一步:
打开Workflow1.cs的代码,在Workflow1里面加入以下两个public属性。
 

   public string UserName

        {

            get;

            set;

        }

        public int UserAge

        {

            get;

            set;

        }

 

于是,加入了属性的此工作流就就受两个参数 UserName 和 UserAge。
 
第二步:
然后修改codeActivity1_ExecuteCode的代码为:
 

   private void codeActivity1_ExecuteCode(object sender, EventArgs e)

        {

            //在这里,书写该活动的执行代码

            Console.WriteLine("UserName:{0},Age:{1},said:Hello APJ !", UserName, UserAge);

        }

 

第三步:

打开Program.cs文件,在里面为调用的Workflow传入参数。工作流的输入参数通过一个字典(Dictionary)对象传入,此Dictionary必须以string为KEY,以object为value。其中Dictionary的KEY应该与调用的Workflow的属性名完全一样,包括大小写。修改后的调用部分的代码如下:

 

         //准备该工作流需要传入的参数,参数放置在一个Dictionary对象中

         Dictionary<string, object> wfArgs = new Dictionary<string, object>();

         wfArgs.Add("UserName", "Ryan");

         wfArgs.Add("UserAge", 27);

 

 

         //WorkflowInstance:是指在工作流引擎中运行的工作流实例。

         //向改工作流实例传入参数

         WorkflowInstance instance = workflowRuntime.CreateWorkflow(

             typeof(APJ.Workflow.HelloApj.Workflow1),wfArgs

              );

 

最后按F5运行查看结果。

 

于是,我们现在可以建立一个Workflow,并且向其传递参数了。

 

点击下面的链接下载本例的源代码。 

APJ.Workflow.HelloApj.rar (18.03 kb)

 

 

 

 

Tags:

技术文章

WF学习笔记-1-创建简单Workflow应用

by Ryan 30. July 2009 16:49
初次学习WF,如有不妥或错误之处,欢迎各位批评指正。
    首先解释一下WF是什么?
    WF全称是 Microsoft Windows Workflow Foundation ,可简称为Workflow或WF,它是一个可扩展框架,用于在 Windows 平台上开发工作流解决方案,VS2005下需要安装.NET3.0框架及Visual Studio 2005 Extensions for Windows Workflow Foundation.exe。VS2008中默认集成WF。
 
    下面通过一个实例来看如何创建一个WF工作流。我们在学习编程语言的时候,第一课一般都是“Hello World”,今天我们也先从一个类似简单的例子开始。就叫“Hello APJ”吧。本节的目的是掌握如何创建一个WF程序。
 
第一步:打开VS2008,按照下图方式,新建一个APJ.Workflow.HelloApj的顺序工作流控制台程序。
 
这个时候的文件清单是这样的。
 
其中:
Program.cs是控制台的主程序。
Workflow1.cs是VS自动添加的一个WF工作流程序。
 
打开Workflow1.cs,进入可视化工作流设计界面,如下图:
左侧工具箱中有许多活动(Actitvity),我们可以将这些活动拖动到右侧的工作区。活动是构成工作流的基本元素,一个完整的工作流由多个活动通过一定的流程控制(比如if else,while等)构成。
 
    什么是活动(Actitvity)?
    WF的主要部件就是活动,活动是WF的基本构成元素,通过将一系列活动按照一定的流程控制组织起来,就形成了一个WF工作流,微软提供了一些常用的活动,当然我们可以自己定义活动,所有的活动都继承自基类:Actitvity。
 
第二步:往Workflow1.cs中拖入一个CodeActitvity,完成后的界面如下图:

注意,图中CodeActitvity旁边有个感叹号,这是工作流设计器的自动检测功能检测到该CodeActitvity不完整,因为没有添加它的ExcuteCode(执行代码),我们可以双击该CodeActitvity,设计器将会自动为其添加ExcuteCode的事件方法,并转到代码页面,代码如下:

using System;

using System.ComponentModel;

using System.ComponentModel.Design;

using System.Collections;

using System.Drawing;

using System.Linq;

using System.Workflow.ComponentModel.Compiler;

using System.Workflow.ComponentModel.Serialization;

using System.Workflow.ComponentModel;

using System.Workflow.ComponentModel.Design;

using System.Workflow.Runtime;

using System.Workflow.Activities;

using System.Workflow.Activities.Rules;

 

namespace APJ.Workflow.HelloApj

{

     public sealed partial class Workflow1: SequentialWorkflowActivity

     {

         public Workflow1()

         {

              InitializeComponent();

         }

 

        private void codeActivity1_ExecuteCode(object sender, EventArgs e)

        {

 

        }

     }

 

}

 

第三步:
其中codeActivity1_ExecuteCode   就是该 CodeActitvity的ExcuteCode调用的方法,我们可以向里面写入需要执行的代码,本例中我们在控制台输出一条:Hello APJ的语句。完善后的代码如后(为节省篇幅,省略掉using部分):

namespace APJ.Workflow.HelloApj

{

     public sealed partial class Workflow1: SequentialWorkflowActivity

     {

         public Workflow1()

         {

              InitializeComponent();

         }

 

        private void codeActivity1_ExecuteCode(object sender, EventArgs e)

        {

            //在这里,书写该活动的执行代码

            Console.WriteLine("Hello APJ !");

        }

     }

 

}

 
第四步:
到这里,一个简单的“Hello APJ”工作流就设计完了,接下来是调用该工作流。我们打开Program.cs文件。看到,VS2008已经默认为我们添加好了自动的调用代码,我们这时如果按F5调试,如果眼睛够快,可以看到一个控制台窗口在眼前稍纵即逝,为了能看清输出的内容,我们在Main方法的后面加入下面两句代码,让窗口挂起。

//等待用户响应退出

Console.WriteLine("Press Enter to exit");

Console.ReadLine();

 

另外,在对Main方法的代码加了些注释,之后的代码如下:

namespace APJ.Workflow.HelloApj

{

    class Program

    {

        static void Main(string[] args)

        {

            //WorkflowRuntime:在工作流的运行环境(宿主)中,为工作流提供运行的引擎。

            using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())

            {

                AutoResetEvent waitHandle = new AutoResetEvent(false);

 

                //以下二个事件是引擎中的某个实例完成后和终止后的事件

                workflowRuntime.WorkflowCompleted +=

                    delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); };

                workflowRuntime.WorkflowTerminated +=

                    delegate(object sender, WorkflowTerminatedEventArgs e)

                    {

                        Console.WriteLine(e.Exception.Message);

                        waitHandle.Set();

                    };

 

                //WorkflowInstance:是指在工作流引擎中运行的工作流实例。

                WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(APJ.Workflow.HelloApj.Workflow1));

 

                //该工作流实例启动

                instance.Start();

 

                //阻止当前现场,以等待异步调用的工作流完成

                waitHandle.WaitOne();

 

 

                //等待用户响应退出

                Console.WriteLine("Press Enter to exit");

                Console.ReadLine();

 

            }

        }

    }

}

 

现在按F5调试运行,看到的界面如下:

 

这样,一个简单的Hello APJ的工作流控制台程序就创建成功了。

 

 

 

 

Tags:

技术文章

【分享】远离感冒:酸奶、红薯、大蒜等9大食物增强免疫力

by ryan 13. July 2009 15:10
最近公司感冒的同事很多,今天看到此文,与大家分享。
 
如何通过饮食来提高免疫力、远离感冒?为实现这个目标,近日,美国MSNBC新闻网向大家介绍了9种食物。

    酸奶:益生菌保护肠道。酸奶中含有益生菌,保护肠道,避免致病细菌的产生。另外,有些酸奶中含有的乳酸菌可以促进血液中白血球的生长。

    红薯:增强皮肤抵抗力。皮肤也是人体免疫系统的一员,是人体抵抗细菌、病毒等外界侵害的第一道屏障。维生素A在结缔皮肤组织过程中起重要作用。而补充维生素A最好的办法就是从食物中获取β胡萝卜素,红薯是获得这种营养的最快途径,它含有丰富的β胡萝卜素,且热量低。

    :抗细菌防流感。哈佛大学的免疫学者发现,连续两周每天喝五杯红茶的人其体内会产生大量的抗病毒干扰素,其含量是不喝茶的人的10倍,这种可以抵抗感染的蛋白可以有效帮助人体抵御流感,同时,还可以减轻食物中毒、伤口感染、脚气甚至是肺结核和疟疾的症状。当然,喝绿茶也具有同样的效果。

    鸡汤:美味的感冒药。鸡肉在烹饪过程中释放出来的半胱氨酸与治疗支气管炎的药物乙酰半胱氨酸非常相似,有盐分的鸡汤可以减轻痰多的症状,因为它与咳嗽药的成分很像。炖鸡汤时加些洋葱和大蒜,可让效果更显著。

    牛肉:补锌增强免疫力。锌在饮食中非常重要,它可以促进白血球的生长,进而帮助人体防范病毒、细菌等有害物质。即使是轻微缺锌,也会增加患传染病的风险。牛肉是人体补充锌的重要来源,所以在冬季,适当进补牛肉,既耐寒又预防流感。

    蘑菇:促进白血球抗感染。长久以来,人们就把蘑菇当作提高免疫力的食物。现在,研究人员们找到了这样做的理由:吃蘑菇可以促进白血球的产生和活动,让它们更具防范性。

    鱼和贝类:补硒防病毒。英国专家研究指出,补充足够的硒可以增加免疫蛋白的数量,进而帮助清理体内的流感病毒。硒主要来源于牡蛎、龙虾、螃蟹和蛤蜊等海鲜类食品。鱼类如大西洋鲑鱼中的欧米伽-3能够帮助血液产生大量的抗流感细胞,也有助于提高人体免疫力。

    大蒜:大蒜素抗感染和细菌。英国研究人员的实验结果表明,食用大蒜可让感冒发生几率降低2/3。经常咀嚼大蒜的人患结肠癌和胃癌的几率也会大大降低。因此,建议每天生吃两瓣蒜,并在烹饪菜肴时加入一些大蒜末。

    燕麦和大麦:健康纤维抗氧化。燕麦和大麦都含有β葡聚糖,这种纤维素有抗菌和抗氧化的作用。食用燕麦和大麦,可以增强免疫力,加速伤口愈合,还能帮助抗生素发挥更佳效果。▲ (郭静超)

 
 

Tags:

Email2Blog

Copyright © 2009 APJ Software

最新评论

Comment RSS

公告

欢迎使用APJ Blog!

日历

<<  May 2012  >>
MoTuWeThFrSaSu
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

View posts in large calendar