2016-09-27 102 views
0

我正在創建工作流application with persistent behaviour and two bookmarks.WF與兩個書籤的持久性。無法堅持第二個書籤

我無法堅持第二個書籤的工作流運行時。

工作流程聲明

1- Start workflow 
2- Ask user to enter name 
3- Create bookmark 
4- Resume bookmark on receiving input from user and show it on UI 
5- Ask user again to enter number 
6- Create bookmark and wait for user input // Unable to persist at this point 
7- Resume bookmark on receiving input from user and show it on UI 

自定義活動

public class WaitForInput<TResult> : NativeActivity<TResult> 
{ 
    [RequiredArgument] 
    public InArgument<string> BookmarkName { get; set; } 

    // indicate to the runtime that this activity can go idle 
    protected override bool CanInduceIdle 
    { 
     get { return true; } 
    } 

    protected override void Execute(NativeActivityContext context) 
    {       
     context.CreateBookmark(this.BookmarkName.Get(context), new BookmarkCallback(OnReadComplete)); 
    } 

    void OnReadComplete(NativeActivityContext context, Bookmark bookmark, object state) 
    {    
     this.Result.Set(context, (TResult)state); 
    } 
} 

Program.cs的

class Program 
{ 
    static AutoResetEvent syncEvent = new AutoResetEvent(false); 
    static Guid id; 

    static void Main(string[] args) 
    { 
     WorkflowApplication app = new WorkflowApplication(new Sequence1()); 
     InstanceStore store = new SqlWorkflowInstanceStore(@"Data Source=.\SQLEXPRESS;Initial Catalog=WF45GettingStartedTutorial;Integrated Security=True"); 
     InstanceHandle handle = store.CreateInstanceHandle(); 
     InstanceView view = store.Execute(handle, new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(30)); 
     handle.Free(); 
     store.DefaultInstanceOwner = view.InstanceOwner; 
     app.InstanceStore = store; 


     app.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e) 
     { 
      return PersistableIdleAction.Unload; 

     }; 

     app.Unloaded = delegate(WorkflowApplicationEventArgs e) 
     { 
      syncEvent.Set(); 
     }; 

     app.Completed = delegate(WorkflowApplicationCompletedEventArgs e) 
     { 
      Console.WriteLine("Workflow {0} Completed.", e.InstanceId); 
     }; 

     id = app.Id; 
     app.Run(); 
     syncEvent.WaitOne(); 

     string text = Console.ReadLine(); 
     app = new WorkflowApplication(new Sequence1()); 
     app.InstanceStore = store; 

     app.Completed = (workflowApplicationCompletedEventArgs) => 
     { 
      Console.WriteLine("WF Bookmark1 has Completed in the {0} state.", 
           workflowApplicationCompletedEventArgs.CompletionState); 
     }; 
     app.Unloaded = (workflowApplicationEventArgs) => 
     { 
      Console.WriteLine("WF Bookmark1 unloaded"); 
      syncEvent.Set(); 
     }; 

     app.Load(id); 
     app.ResumeBookmark("readText", text); 
     syncEvent.WaitOne(); 

     // resume bookmark 2 
     int number = ReadNumberFromConsole(); 
     app = new WorkflowApplication(new Sequence1()); 
     app.InstanceStore = store; 
     app.Completed = (workflowApplicationCompletedEventArgs) => 
     { 
      Console.WriteLine("WF Bookmark2 has Completed in the {0} state.", 
           workflowApplicationCompletedEventArgs.CompletionState); 
     }; 
     app.Unloaded = (workflowApplicationEventArgs) => 
     { 
      Console.WriteLine("WF Bookmark1 unloaded"); 
      syncEvent.Set(); 
     }; 

     app.Load(id); 
     app.ResumeBookmark("readNumber", number); 
     syncEvent.WaitOne(); 
     Console.ReadLine(); 
    }  


} 

問題 工作流運行時提示用戶輸入姓名,並創建書籤,並呼籲PersistableIdleAction.Unload

後,我在控制檯上輸入的用戶名,它重新加載工作流實例,恢復書籤。

它不會爲下一個活動調用PersistableIdleAction.Unload

請幫助

+0

@Maurice,對不起,指導你,但你可以請看看和回答? – immirza

回答

0

問題multi threading concept這裏。

app.Run(); 

以上新線程,因爲我使用WorkflowApplication(而不是WorkflowInvoker)調用它直接啓動工作流運行。

創建第一個書籤時,工作流持續存在&從此線程卸載。

我正在創建新的工作流運行時恢復上面的書籤,因此它有不同的線程。

Solution: I should persist & unload workflow from this thread and not from the 1st first thread. 

我學習它,可能是錯誤的地方,但說實話這是我在上面花了很多以後的理解。

正確版本的Program.cs

namespace Microsoft.Samples.Activities.Statements 
{ 

    class Program 
    { 
     static AutoResetEvent syncEvent = new AutoResetEvent(false); 
     static Guid id; 

     static void Main(string[] args) 
     { 
      // create the workflow app and add handlers for the Idle and Completed actions 
      WorkflowApplication app = new WorkflowApplication(new Sequence1()); 

      //setup persistence 
      InstanceStore store = new SqlWorkflowInstanceStore(@"Data Source=.\SQLEXPRESS;Initial Catalog=WF45GettingStartedTutorial;Integrated Security=True"); 
      InstanceHandle handle = store.CreateInstanceHandle(); 
      InstanceView view = store.Execute(handle, new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(30)); 
      handle.Free(); 
      store.DefaultInstanceOwner = view.InstanceOwner; 
      app.InstanceStore = store; 


      app.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e) 
      { 
       syncEvent.Set(); 
       return PersistableIdleAction.Unload; 

      }; 

      app.Unloaded = delegate(WorkflowApplicationEventArgs e) 
      { 
       syncEvent.Set(); 
      }; 

      app.Completed = delegate(WorkflowApplicationCompletedEventArgs e) 
      { 
       Console.WriteLine("Workflow {0} Completed.", e.InstanceId); 
       syncEvent.Set(); 
      }; 

      // start the application 
      id = app.Id; 
      app.Run(); 
      syncEvent.WaitOne(); 

      // resume bookmark 1 
      string text = Console.ReadLine(); 
      app = new WorkflowApplication(new Sequence1()); 
      app.InstanceStore = store; 

      app.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e) 
      { 
       syncEvent.Set(); 
       return PersistableIdleAction.Unload; 

      }; 

      app.Completed = (workflowApplicationCompletedEventArgs) => 
      { 
       Console.WriteLine("WF Bookmark1 has Completed in the {0} state.", 
            workflowApplicationCompletedEventArgs.CompletionState); 
       syncEvent.Set(); 
      }; 
      app.Unloaded = (workflowApplicationEventArgs) => 
      { 
       Console.WriteLine("WF Bookmark1 unloaded"); 
       syncEvent.Set(); 
      }; 

      app.Load(id); 
      app.ResumeBookmark("readText", text); 
      syncEvent.WaitOne(); 

      // resume bookmark 2 
      int number = ReadNumberFromConsole(); 
      app = new WorkflowApplication(new Sequence1()); 
      app.InstanceStore = store; 
      app.Completed = (workflowApplicationCompletedEventArgs) => 
      { 
       Console.WriteLine("WF Bookmark2 has Completed in the {0} state.", 
            workflowApplicationCompletedEventArgs.CompletionState); 
       syncEvent.Set(); 
      }; 
      app.Unloaded = (workflowApplicationEventArgs) => 
      { 
       Console.WriteLine("WF Bookmark1 unloaded"); 
       syncEvent.Set(); 
      }; 

      app.Load(id); 
      app.ResumeBookmark("readNumber", number); 
      syncEvent.WaitOne(); 

      Console.WriteLine(""); 
      Console.WriteLine("Press [ENTER] to exit..."); 
      Console.ReadLine(); 
     }   

    } 
} 

隨意在這裏糾正我的觀點。 謝謝