我有一个Windows服务,正在运行工作流程。工作流是从数据库加载的XAML(用户可以使用重新设计的设计器定义自己的工作流)。它配置了一个SQLWorkflowInstanceStore实例,以便在变为空闲时保留工作流。 (它基本上来自Microsoft的WCF / WF样本的\ ControllingWorkflowApplications中的示例代码。)
但有时我会收到如下错误:
System.Runtime.DurableInstancing.InstanceOwnerException:InstancePersistenceCommand的执行被中断,因为所有者ID'a426269a-be53-44e1-8580-4d0c396842e8'的实例所有者注册已失效。此错误表示此所有者锁定的所有实例的内存中副本已过时,应与InstanceHandles一起丢弃。通常,最好通过重新启动主机来处理此错误。
我一直在努力找到原因,但是在开发中很难重现,但在生产服务器上,我偶尔会得到它。我发现一个提示:当我查看LockOwnersTable时,我发现LockOnwersTable lockexpiration设置为01/01/2000 0:0:0并且它不再被更新,而在正常情况下应该每x秒更新一次主机锁更新期......
那么,为什么SQLWorkflowInstanceStore会停止更新此LockExpiration,以及如何检测它的原因?
答案 0 :(得分:1)
这是因为有后台程序在运行并尝试每隔30秒扩展一次实例存储的锁定,并且一旦连接失败连接到SQL服务,它就会将此实例存储标记为无效。 如果从[LockOwnersTable]表中删除实例存储记录,则可以看到相同的行为。 建议的解决方案是,当此异常触发时,您需要释放旧的实例存储并初始化新的
public class WorkflowInstanceStore : IWorkflowInstanceStore, IDisposable
{
public WorkflowInstanceStore(string connectionString)
{
_instanceStore = new SqlWorkflowInstanceStore(connectionString);
InstanceHandle handle = _instanceStore.CreateInstanceHandle();
InstanceView view = _instanceStore.Execute(handle,
new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(30));
handle.Free();
_instanceStore.DefaultInstanceOwner = view.InstanceOwner;
}
public InstanceStore Store
{
get { return _instanceStore; }
}
public void Dispose()
{
if (null != _instanceStore)
{
var deleteOwner = new DeleteWorkflowOwnerCommand();
InstanceHandle handle = _instanceStore.CreateInstanceHandle();
_instanceStore.Execute(handle, deleteOwner, TimeSpan.FromSeconds(10));
handle.Free();
}
}
private InstanceStore _instanceStore;
}
您可以在此链接中找到创建实例存储句柄的最佳做法 Workflow Instance Store Best practices
答案 1 :(得分:1)
这是一个老话题,但我偶然发现了同样的问题。
Damir's Corner建议在调用实例存储之前检查实例句柄是否仍然有效。我在此引用整篇文章:
Workflow Foundation的某些方面仍然记录不完整;持久性框架就是其中之一。以下代码段通常用于设置实例存储:
var instanceStore = new SqlWorkflowInstanceStore(connectionString);
instanceStore.HostLockRenewalPeriod = TimeSpan.FromSeconds(30);
var instanceHandle = instanceStore.CreateInstanceHandle();
var view = instanceStore.Execute(instanceHandle,
new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(10));
instanceStore.DefaultInstanceOwner = view.InstanceOwner;
很难找到所有这一切的详细解释 做;说实话,通常没有必要。至少不是, 直到你开始遇到问题,例如InstanceOwnerException:
InstancePersistenceCommand的执行被中断,因为 所有者注册所有者ID ' 9938cd6d-a9cb-49ad-a492-7c087dcc93af'已变得无效。这个错误 表示由此锁定的所有实例的内存中副本 老板已经变得陈旧,应该随便丢弃 InstanceHandles。通常,最好通过重新启动来处理此错误 主持人。
该错误与HostLockRenewalPeriod属性密切相关 它定义了获取的实例句柄在没有的情况下有效的时间 更新。如果您尝试在实例存储时监视数据库 如果实例化了有效的实例句柄,您会注意到 [System.Activities.DurableInstancing]。[ExtendLock]被调用 定期。该存储过程负责更新 处理。如果由于某种原因无法在指定范围内调用它 HostLockRenewalPeriod,将抛出上述异常 当试图坚持工作流程时。这种情况的典型原因是 由于维护或联网而暂时无法访问数据库 问题。它不是经常发生的事情,但它必然会受到影响 如果你有一个很长的实例存储,例如一直在 运行工作流主机,例如Windows服务。
幸运的是,一旦你解决了这个问题并不是那么困难 知道它的原因。在使用实例存储之前,您应该 如果手柄仍然有效,请务必检查;并更新它,如果不是:
if (!instanceHandle.IsValid)
{
instanceHandle = instanceStore.CreateInstanceHandle();
var view = instanceStore.Execute(instanceHandle,
new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(10));
instanceStore.DefaultInstanceOwner = view.InstanceOwner;
}
建议,它确实比主机重启更具侵入性 通过错误消息。
答案 2 :(得分:0)
您必须确定所有者用户的到期时间
这里我是如何处理这个问题的
public SqlWorkflowInstanceStore SetupSqlpersistenceStore()
{
SqlWorkflowInstanceStore sqlWFInstanceStore = new SqlWorkflowInstanceStore(ConfigurationManager.ConnectionStrings["DB_WWFConnectionString"].ConnectionString);
sqlWFInstanceStore.InstanceCompletionAction = InstanceCompletionAction.DeleteAll;
InstanceHandle handle = sqlWFInstanceStore.CreateInstanceHandle();
InstanceView view = sqlWFInstanceStore.Execute(handle, new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(30));
handle.Free();
sqlWFInstanceStore.DefaultInstanceOwner = view.InstanceOwner;
return sqlWFInstanceStore;
}
以及如何使用此方法
wfApp.InstanceStore = SetupSqlpersistenceStore();
希望得到这个帮助