2010-04-03 79 views
2

我們有一個狀態機工作流,用於維護用戶提交的應用程序的狀態。我遇到的其中一個問題與工作流終止有關。在其中一個州,我有一個錯誤。當應用程序達到該狀態時,它會拋出一個異常,並因此調用工作流的終止事件,並從持久性數據庫中刪除特定的工作流實例。所以我無法再加載該工作流程實例。我希望,如果其中一個州出現錯誤,會拋出異常(以便我們知道問題是什麼),但是整個工作流實例不應該消失。錯誤處理程序活動能否確保工作流程不會終止。另外,有沒有辦法,當調用terminate事件時,實例不會從持久性存儲中被刪除。狀態機WF:工作流終止的問題

感謝您的任何幫助/建議。

回答

1

當一個異常被在工作流中拋出,異常會有效地「冒泡」通過活動祖先,直到它可以是:

  1. 由故障處理程序活動
  2. 已處理到達根部活性(即:工作流程本身),此時工作流程將終止。

最好的做法是在正確的位置爲所有可能的異常創建錯誤處理程序。使用錯誤處理程序活動可以恢復工作流實例,並有效地將狀態機設置回可用狀態,而不是終止狀態機。

一旦工作流已經終止它是不可用的,所以一旦發生終止,這就是爲什麼它被移除有將其保留在持久性存儲沒有任何好處。所以你可以看到,關鍵是要阻止它意外終止。

最後一個提示。當工作流程終止時,導致終止的異常將作爲WorkflowTerminatedEventArgs對象的Exception屬性發送給事件偵聽器。我絕對會建議有某種記錄機制,以趕上和地方輸出它,這樣如果遇到在將來由於某種原因未捕獲的錯誤,它會更容易追蹤下來。

0

我創建了一個自定義的SQL工作流持久化服務,以防止工作流程與實際終止 - 從而讓工作流在以前的狀態導致了錯誤發生轉變前:

public class CustomSqlWorkflowPersistenceService : SqlWorkflowPersistenceService 
    { 
     public CustomSqlWorkflowPersistenceService (string connectionString) : base(connectionString) 
     { 
     } 

     public CustomSqlWorkflowPersistenceService (NameValueCollection parameters) : base(parameters) 
     { 
     } 

     public CustomSqlWorkflowPersistenceService (string connectionString, bool unloadOnIdle, TimeSpan instanceOwnershipDuration, TimeSpan loadingInterval) : base(connectionString, unloadOnIdle, instanceOwnershipDuration, loadingInterval) 
     { 
     } 

     protected override void SaveWorkflowInstanceState(Activity rootActivity, bool unlock) 
     { 
      WorkflowStatus workflowStatus = GetWorkflowStatus(rootActivity); 
      if (workflowStatus == WorkflowStatus.Terminated) 
      { 
       string workflowError = GetSuspendOrTerminateInfo(rootActivity); 
       if (!string.IsNullOrEmpty(workflowError)) 
       { 
        string error = string.Format("Workflow terminated, forcing an abort! {0}", workflowError); 
        throw new Exception(error); 
       } 
      } 
      base.SaveWorkflowInstanceState(rootActivity, unlock); 
     } 
    } 

這顯然會如果你想迫使WF終止,那就太痛苦了,但我相信你可以解決這個問題。

0

我使用SqlWorkflowPersistence,爲修復此我沒了下文:

在「WorkflowPersistence」 DB,我們有SP「InsertInstanceState」這將刪除實例。我評論了刪除實例的代碼。

看起來像它的工作,但我不知道這是否是正確的方法。

部分SP顯示如下,我改變了。

IF 
@status=1 OR @status=3   
    BEGIN  

/* DELETE FROM [dbo].[InstanceState] WHERE [email protected] AND ((ownerID = @ownerID AND ownedUntil>[email protected]) 
OR (ownerID IS NULL AND @ownerID IS NULL))   
*/ 
    END