这个工作流异常时常能见到: 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.
如何解决呢?吃完午饭再说吧!