WorkflowApplication を使用して IIS で WF4 ワークフローをホストするアプリケーションがあります。
ワークフローは (再ホストされたワークフロー デザイナーを使用して) ユーザーによって定義され、xml はデータベースに格納されます。次に、アプリケーションを使用したユーザー アクションに応じて、データベースで xml が選択され、ワークフローが作成/再開されます。
私の問題は、ワークフローがブックマークに到達してアイドル状態になると、さまざまな時間ロックされたままになることです。次に、ユーザーがこのワークフローに関して別のアクションを実行しようとすると、次の例外が発生しました。
インスタンス '52da4562-896e-4959-ae40-5cd016c4ae79' が別のインスタンス所有者によってロックされているため、InstancePersistenceCommand の実行が中断されました。このエラーは通常、別のホストにインスタンスがロードされているために発生します。インスタンスをロックしている所有者またはホストのインスタンス所有者 ID は「d7339374-2285-45b9-b4ea-97b18c968c19」です。
次は、コードの一部です。
ワークフローがアイドル状態になったら、アンロードするように指定します。
private PersistableIdleAction handlePersistableIdle(WorkflowApplicationIdleEventArgs arg)
{
this.Logger.DebugFormat("Workflow '{1}' is persistableIdle on review '{0}'", arg.GetReviewId(), arg.InstanceId);
return PersistableIdleAction.Unload;
}
必要な WorkflowApplication ごとに、新しい SqlWorkflowInstanceStore を作成します。
var store = new SqlWorkflowInstanceStore(this._connectionString);
store.RunnableInstancesDetectionPeriod = TimeSpan.FromSeconds(5);
store.InstanceLockedExceptionAction = InstanceLockedExceptionAction.BasicRetry;
これが私のWorkflowApplicationの作成方法です
WorkflowApplication wfApp = new WorkflowApplication(root.RootActivity);
wfApp.Extensions.Add(...);
wfApp.InstanceStore = this.createStore();
wfApp.PersistableIdle = this.handlePersistableIdle;
wfApp.OnUnhandledException = this.handleException;
wfApp.Idle = this.handleIdle;
wfApp.Unloaded = this.handleUnloaded;
wfApp.Aborted = this.handleAborted;
wfApp.SynchronizationContext = new CustomSynchronizationContext();
return wfApp;
次に、Run メソッドを呼び出して開始します。いくつかの説明:
- root.RootActivity: データベースに保存されたワークフロー XML から作成されたアクティビティです
- CustomSynchronizationContext: 承認を処理する同期コンテキスト
- handleUnloaded メソッドで、ワークフローがアンロードされたときにログに記録し、ワークフローが正しくアンロードされていることを確認しました次のユーザー アクションの前ですが、ワークフローがアンロードされた後もロックされたままになっているようです (?)
その後、ワークフローを再開する必要がある場合は、同じ方法でワークフローを作成し、次のように呼び出します。
wfApp.Load(workflowInstanceId);
上記で指定された「ロックされた」例外をスローします。数分待ってから再試行すると、問題なく動作します。
ここで、所有者を設定する必要があるという投稿を読みました。だから私はまた、このコードを使用して所有者が設定された静的 SqlWorkflowInstanceStore を使用してみました:
if (_sqlWorkflowInstanceStore != null)
return _sqlWorkflowInstanceStore;
lock (_mutex)
{
if (_sqlWorkflowInstanceStore != null)
return _sqlWorkflowInstanceStore;
// Configure store
_sqlWorkflowInstanceStore = new SqlWorkflowInstanceStore(this._connectionString);
_sqlWorkflowInstanceStore.RunnableInstancesDetectionPeriod = TimeSpan.FromSeconds(5);
_sqlWorkflowInstanceStore.InstanceLockedExceptionAction = InstanceLockedExceptionAction.BasicRetry;
// Set owner - Store will be read-only beyond this point and will not be configurable anymore
var handle = _sqlWorkflowInstanceStore.CreateInstanceHandle();
var view = _sqlWorkflowInstanceStore.Execute(handle, new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(5));
handle.Free();
_sqlWorkflowInstanceStore.DefaultInstanceOwner = view.InstanceOwner;
}
return _sqlWorkflowInstanceStore;
しかし、私はこの種の例外を持っています:
所有者 ID '9efb4434-8560-469f-9d03-098a2d48821e' のインスタンス所有者登録が無効になったため、InstancePersistenceCommand の実行が中断されました。このエラーは、この所有者によってロックされたすべてのインスタンスのメモリ内コピーが古くなり、InstanceHandles と共に破棄する必要があることを示しています。通常、このエラーはホストを再起動することで処理するのが最適です。
ワークフローがアンロードされたときにワークフローのロックがすぐに解除されることを確認する方法を知っている人はいますか? WorkflowServiceHost (WorkflowIdleBehavior を使用) でこれを行っている投稿を見たことがありますが、ここでは WorkflowServiceHost を使用しておらず、WorkflowApplication を使用しています。
助けてくれてありがとう!