[英]WF persistency with two bookmark. unable to persist second bookmark
我正在創建application with persistent behaviour and two bookmarks.
Workflow application with persistent behaviour and two bookmarks.
我無法為第二個書簽保留工作流運行時。
工作流程聲明
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
。
請幫助
問題在於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();
}
}
}
請隨意糾正我的觀點。 謝謝
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.