這種情況下,使用WF的持久性功能發光。它允許您將工作流實例持久化到數據庫,以允許完成一些長時間運行的操作。一旦完成,第二個線程或進程可以重新提供工作流程實例並使其恢復。
首先您向工作流應用程序指定一個工作流實例存儲區。 Microsoft提供了一個您可以使用的SQL workflow instance store implementation,並提供了可以在SQL Server上運行的SQL腳本。
namespace MySolution.MyWorkflowApp
{
using System.Activities;
using System.Activities.DurableInstancing;
using System.Activities.Statements;
using System.Threading;
internal static class Program
{
internal static void Main(string[] args)
{
var autoResetEvent = new AutoResetEvent(false);
var workflowApp = new WorkflowApplication(new Sequence());
workflowApp.InstanceStore = new SqlWorkflowInstanceStore("server=mySqlServer;initial catalog=myWfDb;...");
workflowApp.Completed += e => autoResetEvent.Set();
workflowApp.Unloaded += e => autoResetEvent.Set();
workflowApp.Aborted += e => autoResetEvent.Set();
workflowApp.Run();
autoResetEvent.WaitOne();
}
}
}
您的活動將啓動一個輔助進程/線程,它將實際執行保存操作。有多種方法可以做到這一點:
- 在輔助線程
- 通過異步調用Web方法,它實際執行保存操作
您的活動的繁重會看起來像這樣:
public sealed class WebSaveActivity : NativeActivity
{
public InArgument<MyBigObject> ObjectToSave { get; set; }
protected override bool CanInduceIdle
{
get
{
// This notifies the WF engine that the activity can be unloaded/persisted to an instance store.
return true;
}
}
protected override void Execute(NativeActivityContext context)
{
var currentBigObject = this.ObjectToSave.Get(context);
currentBigObject.WorkflowInstanceId = context.WorkflowInstanceId;
StartSaveOperationAsync(this.ObjectToSave.Get(context)); // This method should offload the actual save process to a thread or even a web method, then return immediately.
// This tells the WF engine that the workflow instance can be suspended and persisted to the instance store.
context.CreateBookmark("MySaveOperation", AfterSaveCompletesCallback);
}
private void AfterSaveCompletesCallback(NativeActivityContext context, Bookmark bookmark, object value)
{
// Do more things after the save completes.
var saved = (bool) value;
if (saved)
{
// yay!
}
else
{
// boo!!!
}
}
}
書籤創建信號給WF引擎,工作流實例可以從內存中卸載直到某些東西被喚醒e工作流實例。
在您的方案中,您希望工作流程在長時間保存操作完成後恢復。讓我們假設該StartSaveOperationAsync
方法寫一個小的消息,某種類型的隊列中,第二個線程或進程輪詢執行保存操作:
public static void StartSaveOperationAsync(MyBigObject myObjectToSave)
{
var targetQueue = new MessageQueue(".\private$\pendingSaveOperations");
var message = new Message(myObjectToSave);
targetQueue.Send(message);
}
在我的第二個過程,那麼我可以輪詢新保存隊列請求並重新保存持久化的工作流實例,以便在保存操作完成後恢復。假設下面的方法是在不同的控制檯應用程序:
internal static void PollQueue()
{
var targetQueue = new MessageQueue(@".\private$\pendingSaveOperations");
while (true)
{
// This waits for a message to arrive on the queue.
var message = targetQueue.Receive();
var myObjectToSave = message.Body as MyBigObject;
// Perform the long running save operation
LongRunningSave(myObjectToSave);
// Once the save operation finishes, you can resume the associated workflow.
var autoResetEvent = new AutoResetEvent(false);
var workflowApp = new WorkflowApplication(new Sequence());
workflowApp.InstanceStore = new SqlWorkflowInstanceStore("server=mySqlServer;initial catalog=myWfDb;...");
workflowApp.Completed += e => autoResetEvent.Set();
workflowApp.Unloaded += e => autoResetEvent.Set();
workflowApp.Aborted += e => autoResetEvent.Set();
// I'm assuming the object to save has a field somewhere that refers the workflow instance that's running it.
workflowApp.Load(myObjectToSave.WorkflowInstanceId);
workflowApp.ResumeBookmark("LongSaveOperation", true); // The 'true' parameter is just our way of saying the save completed successfully. You can use any object type you desire here.
autoResetEvent.WaitOne();
}
}
private static void LongRunningSave(object myObjectToSave)
{
throw new NotImplementedException();
}
public class MyBigObject
{
public Guid WorkflowInstanceId { get; set; } = Guid.NewGuid();
}
現在長時間運行保存操作不會妨礙工作流引擎,它會通過不保持工作流實例在內存中更有效地利用系統資源很長一段時間。
不,我希望工作流被暫停(或進入空閒模式)直到'WebSave'完成,因此在接下來的活動中我可以使用結果。 – mehrandvd