不,这不是书签的使用方式。当工作流必须等待来自外部流程的输入时,使用书签。
例如:我有一个文档审批工作流,在某个时间点,该工作流必须等待人工审阅者对文档给出 OK。当调用ResumeBookmark 时,工作流将被运行时闲置并再次激活,而不是将工作流实例保存在内存中。
在您的情况下,您的工作流不能闲置,因为它有一个在其上下文中运行的操作。该操作是您的任务,顺便说一句,它是一种即发即弃的任务,因此 WF 无法处理严重的故障。
现在,对于一个可能的解决方案,您可能会考虑让其他进程调用 GetAndSave 方法并让该进程最终调用 WF 上的 ResumeBookmark,以便运行时可以空闲工作流。该流程甚至可以与托管您的工作流程的流程相同。
有关示例,请参阅this blogpost。想象一下,您无需等待人类在控制台中输入内容,而是执行了长时间运行的任务。
您没有指定活动之后会发生什么,但请注意,当书签恢复时,可以将数据返回到工作流。因此,GetAndSave 的任何结果,即使它只是一个错误代码,您也可以使用它来决定如何进一步配合工作流程中的其他活动。
希望这对您有意义,并且您会看到我试图概述的可能的解决方案。
编辑
关于在 WF 中使用任务或异步/等待的快速说明。 AFAIK 没有方法可以覆盖返回的任务,因此您要么必须使用 .Wait() 或 .Result 阻止它们,要么忘记它。因为如果你不能等待它们,那么在工作流执行期间就会发生坏事,因为其他活动可能会在使用 Tasks 的活动完成其工作之前开始。
在开发 WF 运行时,Task 的整个概念还很年轻,因此 WF 运行时没有/不适合它们。
编辑 2:
示例实现(基于this excellent official documentation)
您的活动几乎是空的:
public sealed class TriggerDownload : NativeActivity<string>
{
[RequiredArgument]
public InArgument<string> BookmarkName { get; set; }
protected override void Execute(NativeActivityContext context)
{
// Create a Bookmark and wait for it to be resumed.
context.CreateBookmark(BookmarkName.Get(context),
new BookmarkCallback(OnResumeBookmark));
}
protected override bool CanInduceIdle
{
get { return true; }
}
public void OnResumeBookmark(NativeActivityContext context, Bookmark bookmark, object obj)
{
// When the Bookmark is resumed, assign its value to
// the Result argument. (This depends on whether you have a result on your GetData method like a string with a result code or something)
Result.Set(context, (string)obj);
}
}
它向工作流运行时发出信号,表明工作流可以空闲以及如何恢复。
现在,对于工作流运行时配置:
WorkflowApplication wfApp = new WorkflowApplication(<Your WF>);
// Workflow lifecycle events omitted except idle.
AutoResetEvent idleEvent = new AutoResetEvent(false);
wfApp.Idle = delegate(WorkflowApplicationIdleEventArgs e)
{
idleEvent.Set();
};
// Run the workflow.
wfApp.Run();
// Wait for the workflow to go idle before starting the download
idleEvent.WaitOne();
// Start the download and resume the bookmark when finished.
var result = await Task.Run(() => GetAndSave());
BookmarkResumptionResult result = wfApp.ResumeBookmark(new Bookmark("GetData"), result);
// Possible BookmarkResumptionResult values:
// Success, NotFound, or NotReady
Console.WriteLine("BookmarkResumptionResult: {0}", result);