zoukankan      html  css  js  c++  java
  • 对WF工作流异常(Event on interface type for instance id cannot be delivered)的一点总结.

    这个工作流异常时常能见到: Event "SubmitEvent" on interface type "WorkflowConsoleApplication2.ISalesOrderService" for instance id "8ed729b9-1dd1-46a2-b7ef-fb5a75eeb7fd" cannot be delivered.

    看ms的帖子说有多种可能导致此异常, 因此, 在这里罗列总结一下自己曾经遇到过的和解决方法.

    1.参数序列化的问题.

    1.1 先从一个状态机工作流的例子开始, 比如说要处理订单状态, 提交, 审批通过或拒绝, 结束.

    先把工作流鸟瞰截图share一下, 简简单单, 总共三个状态, 每个步骤里一个handleExternalEventActivity, 一个自定义的CodeAcitvity和一个SetStateActivity.


    1.2 开始从头描述代码

         要处理的订单类代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace WorkflowConsoleApplication2
    {
        public class SalesOrder
        {
            public int SalesOrderID { set; get; }
            public string CustomerName { set; get; }
            public string ProductName { set; get; }
            public int Amount { set; get; }
            public decimal UnitPrice { set; get; }
            public decimal TotalMoney { set; get; }
            public int Status { set; get; }
        }
    }

      服务接口:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Workflow.Activities;

    namespace WorkflowConsoleApplication2
    {
        [ExternalDataExchange]
        public interface ISalesOrderService
        {
            event EventHandler<SalesOrderArgs> SubmitEvent;
            event EventHandler<SalesOrderArgs> ApprovalEvent;
            event EventHandler<SalesOrderArgs> RejectEvent;
        }
    }

       本地服务代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace WorkflowConsoleApplication2
    {
        public class SalesOrderService: ISalesOrderService
        {
            public event EventHandler<SalesOrderArgs> SubmitEvent;
            public event EventHandler<SalesOrderArgs> ApprovalEvent;
            public event EventHandler<SalesOrderArgs> RejectEvent;

            public void FireSubmitEvent(Guid instanceID, SalesOrder salesOrder)
            {
                if (SubmitEvent != null)
                {
                    SalesOrderArgs args = new SalesOrderArgs(instanceID, salesOrder);
                    SubmitEvent(null, args);
                }
            }

            public void FireApprovalEvent(Guid instanceID, SalesOrder salesOrder)
            {
                if (ApprovalEvent != null)
                {
                    SalesOrderArgs args = new SalesOrderArgs(instanceID, salesOrder);
                    ApprovalEvent(null, args);
                }
            }

            public void FireRejectEvent(Guid instanceID, SalesOrder salesOrder)
            {
                if (RejectEvent != null)
                {
                    SalesOrderArgs args = new SalesOrderArgs(instanceID, salesOrder);
                    RejectEvent(null, args);
                }
            }
        }
    }

      事件参数类:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Workflow.Activities;

    namespace WorkflowConsoleApplication2
    {
        [Serializable]
        public class SalesOrderArgs : ExternalDataEventArgs
        {
            public SalesOrder SalesOrder { set; get; }

            public SalesOrderArgs(Guid instanceID, SalesOrder salesOrder) : base(instanceID)
            {
                this.SalesOrder = salesOrder;
            }
        }
    }

      工作流类: 

    using System;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Collections;
    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 WorkflowConsoleApplication2
    {
        public sealed partial class Workflow1 : StateMachineWorkflowActivity
        {
            public static DependencyProperty SalesOrderArgsProperty = DependencyProperty.Register("SalesOrderArgs", typeof(SalesOrderArgs), typeof(Workflow1));

            [Description("SalesOrderArgs")]
            [Category("SalesOrderArgs Category")]
            [Browsable(true)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
            public SalesOrderArgs SalesOrderArgs
            {
                get
                {
                    return ((SalesOrderArgs)(base.GetValue(Workflow1.SalesOrderArgsProperty)));
                }
                set
                {
                    base.SetValue(Workflow1.SalesOrderArgsProperty, value);
                }
            }

            public Workflow1()
            {
                InitializeComponent();
            }

            private void HandleSumitInvoked(object sender, ExternalDataEventArgs e)
            {
                Console.WriteLine("HandleSumitInvoked");
            }

            private void HandleApprovalInvoked(object sender, ExternalDataEventArgs e)
            {
                Console.WriteLine("HandleApprovalInvoked");
            }

            private void HandleRejectInvoked(object sender, ExternalDataEventArgs e)
            {
                Console.WriteLine("HandleRejectInvoked");
            }

        }

    }

      自定义CodeActivity类,其它两类一样,就不贴出来了:

    using System;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Collections;
    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 WorkflowConsoleApplication2
    {
        public partial class SubmitActivity : Activity
        {
            public static DependencyProperty SalesOrderArgsProperty = DependencyProperty.Register("SalesOrderArgs", typeof(SalesOrderArgs), typeof(SubmitActivity));

            [Description("SalesOrderArgs")]
            [Category("SalesOrderArgs Category")]
            [Browsable(true)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
            public SalesOrderArgs SalesOrderArgs
            {
                get
                {
                    return ((SalesOrderArgs)(base.GetValue(SubmitActivity.SalesOrderArgsProperty)));
                }
                set
                {
                    base.SetValue(SubmitActivity.SalesOrderArgsProperty, value);
                }
            }

            public SubmitActivity()
            {
                InitializeComponent();
            }

            protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
            {
                this.SalesOrderArgs.SalesOrder.Status = 0;
                return base.Execute(executionContext);
            }
        }
    }

      启动Main函数:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Workflow.Runtime;
    using System.Workflow.Runtime.Hosting;
    using System.Workflow.Activities;

    namespace WorkflowConsoleApplication2
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
                {
                    AutoResetEvent waitHandle = new AutoResetEvent(false);
                    workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) {
                        SalesOrderArgs soArgs = (SalesOrderArgs)e.OutputParameters["SalesOrderArgs"];
                        Console.WriteLine(soArgs.SalesOrder.SalesOrderID + soArgs.SalesOrder.CustomerName + soArgs.SalesOrder.ProductName + " status" + soArgs.SalesOrder.Status);
                        waitHandle.Set();
                    };
                    workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
                    {
                        Console.WriteLine(e.Exception.Message);
                        waitHandle.Set();
                    };

                    //创建数据交换服务
                    ExternalDataExchangeService dataService = new ExternalDataExchangeService();

                    //将数据交换服务加入运行时
                    workflowRuntime.AddService(dataService);

                    //创建local数据接口服务
                    SalesOrderService localService = new SalesOrderService();

                    //将local数据接口服务加入数据交换服务
                    dataService.AddService(localService);

                    WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(WorkflowConsoleApplication2.Workflow1));

                    instance.Start();                          

                    SalesOrder so = new SalesOrder() { SalesOrderID = 100, CustomerName = "上海汽车股份有限公司", ProductName = "ACM", UnitPrice = 1200, Amount = 10, TotalMoney = 12000, Status = -1 };

                    localService.FireSubmitEvent(instance.InstanceId, so);    
                   

                    waitHandle.WaitOne();
                }
            }
        }
    }

    1.3 调试运行

      上边的代码看似无懈可击,但一运行,就遇到异常.

       

       点击下面的View Detail链接:

        

      可见真正的问题是:EventArgs not serializable.

      可是回头看SalesOrderArgs,该类已经设置了[Serializable]属性,怎么还会错呢?莫非是SalesOrder类?它倒没有设置Serializable,给它也设置一下。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace WorkflowConsoleApplication2
    {
        [Serializable]
        public class SalesOrder
        {
            public int SalesOrderID { set; get; }
            public string CustomerName { set; get; }
            public string ProductName { set; get; }
            public int Amount { set; get; }
            public decimal UnitPrice { set; get; }
            public decimal TotalMoney { set; get; }
            public int Status { set; get; }
        }
    }

      再运行,ok,成功了!

      也就是说,只要是参数类中用到参数,都必须能序列化才可以,而不能以为给参数类加了序列化标记就算万事大吉了。

    2.消息队列问题。

      如果在Main函数中跳过submit状态,直接激发approval事件,代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Workflow.Runtime;
    using System.Workflow.Runtime.Hosting;
    using System.Workflow.Activities;

    namespace WorkflowConsoleApplication2
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
                {
                    AutoResetEvent waitHandle = new AutoResetEvent(false);
                    workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) {
                        SalesOrderArgs soArgs = (SalesOrderArgs)e.OutputParameters["SalesOrderArgs"];
                        Console.WriteLine(soArgs.SalesOrder.SalesOrderID + soArgs.SalesOrder.CustomerName + soArgs.SalesOrder.ProductName + " status" + soArgs.SalesOrder.Status);
                        waitHandle.Set();
                    };
                    workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
                    {
                        Console.WriteLine(e.Exception.Message);
                        waitHandle.Set();
                    };

                    //创建数据交换服务
                    ExternalDataExchangeService dataService = new ExternalDataExchangeService();

                    //将数据交换服务加入运行时
                    workflowRuntime.AddService(dataService);

                    //创建local数据接口服务
                    SalesOrderService localService = new SalesOrderService();

                    //将local数据接口服务加入数据交换服务
                    dataService.AddService(localService);

                    WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(WorkflowConsoleApplication2.Workflow1));

                    instance.Start();                          

                    SalesOrder so = new SalesOrder() { SalesOrderID = 100, CustomerName = "上海汽车股份有限公司", ProductName = "ACM", UnitPrice = 1200, Amount = 10, TotalMoney = 12000, Status = -1 };

                    //localService.FireSubmitEvent(instance.InstanceId, so);    
                    localService.FireApprovalEvent(instance.InstanceId, so);    
                   

                    waitHandle.WaitOne();
                }
            }
        }

         一运行,得到异常图如下:

      

      

      可见,真正的错误如下:

      "Queue 'Message Properties
             Interface Type:WorkflowConsoleApplication2.ISalesOrderService
             Method Name:ApprovalEvent
             CorrelationValues:
            ' is not enabled.

      如何解决呢?吃完午饭再说吧!

  • 相关阅读:
    解密:腾讯如何打造一款实时对战手游
    哪是来的自尊心
    NODEJS 在Centos下面的自动启动
    nodejs的安装与配置
    基于Centos7+Nginx+Tomcat8的负载均衡服务器的搭建
    门店管理系统架构-(1)
    PHP 使用编码树,生成easyui中的tree样式
    Apache 打开网页的时候等待时间过长的解决方案
    Apache2.4开启GZIP功能
    Apache+Tomcat实现负载均衡
  • 原文地址:https://www.cnblogs.com/liuzhendong/p/2289903.html
Copyright © 2011-2022 走看看