对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.

 

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

 

posted on 2011-12-16 11:10  BobLiu  阅读(752)  评论(8编辑  收藏  举报