C# 具有两个书签的WF持久性。无法保留第二个书签

C# 具有两个书签的WF持久性。无法保留第二个书签,c#,.net,workflow,workflow-foundation-4,workflow-activity,C#,.net,Workflow,Workflow Foundation 4,Workflow Activity,我正在创建具有持久行为和两个书签的工作流应用程序。 我无法为第二个书签持久化工作流运行时 工作流声明 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

我正在创建具有持久行为和两个书签的工作流
应用程序。

我无法为第二个书签持久化工作流运行时

工作流声明

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);
    }
}
问题 工作流运行时要求用户输入名称并创建书签,然后调用PersistableIdleAction.Unload

在控制台上输入用户名后,它会重新加载工作流实例并恢复书签

它不会为下一个活动调用
persistableidreaction.Unload


请帮忙

这里的问题是
多线程概念的问题

app.Run();
上线在新线程上启动工作流运行时,因为我正在使用
WorkflowApplication
(而不是
WorkflowInvoker
)调用它

创建第一个书签时,工作流被持久化并从此线程中卸载

我在恢复上面的书签时创建了新的工作流运行时,所以它有不同的线程

Solution: I should persist & unload workflow from this thread and not from the 1st first thread.
我知道这可能是错误的地方,但老实说,这是我花了很多钱后才明白的

程序.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();
        }           

    } 
}
请随意更正我的观点。
谢谢

这里的问题是
多线程概念的问题

app.Run();
上线在新线程上启动工作流运行时,因为我正在使用
WorkflowApplication
(而不是
WorkflowInvoker
)调用它

创建第一个书签时,工作流被持久化并从此线程中卸载

我在恢复上面的书签时创建了新的工作流运行时,所以它有不同的线程

Solution: I should persist & unload workflow from this thread and not from the 1st first thread.
我知道这可能是错误的地方,但老实说,这是我花了很多钱后才明白的

程序.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();
        }           

    } 
}
请随意更正我的观点。
谢谢

@Maurice,抱歉指导您,但您能看一下并回答吗?@Maurice,抱歉指导您,但您能看一下并回答吗?