これは通常、コンソールでユーザー入力を待機する長時間実行ワークフローの最小の例です。(このコードは実行されませんでした。例としてのみ取り上げてください)
/// Activity that waits on bookmark for
/// someone to send it some text
///
public sealed class ReadLine: NativeActivity<string>
{
[RequiredArgument]
public InArgument<string> BookmarkName { get; set; }
protected override bool CanInduceIdle
{
get
{
return true;
}
}
protected override void Execute(NativeActivityContext context)
{
context.CreateBookmark(
BookmarkName.Get(context),
new BookmarkCallback(OnReadComplete));
}
void OnReadComplete(NativeActivityContext context, Bookmark bookmark, object state)
{
context.SetValue(base.Result, state as string);
}
}
/// Program that uses ReadLine activity's bookmark to persist
/// workflow and waits for user input to resume it
///
public class Program
{
static InstanceStore InstanceStore;
static Activity Activity = GetExampleActivity();
static AutoResetEvent unloadEvent = new AutoResetEvent(false);
static Guid WfId;
static WorkflowApplication WfApp;
const string READ_LINE_BOOKMARK = "ReadLineBookMark";
static void Main()
{
CreateInstanceStore();
CreateWorkflowApp();
// Start workflow application and wait for input
StartAndUnload();
//Get user input and send it to ReadLine bookmark reviving workflow
GetInputAndComplete();
}
static void StartAndUnload()
{
WfApp.Run();
WfId = app.Id;
// !! Workflow will go idle on bookmark, no need to call Unload()
unloadEvent.WaitOne();
}
static void GetInputAndComplete()
{
var input = Console.ReadLine();
// We've the text input, let's resume this thing
WfApp.Load(WfId);
WfApp.ResumeBookmark(READ_LINE_BOOKMARK, input);
unloadEvent.WaitOne();
}
static void CreateInstanceStore()
{
InstanceStore = new SqlWorkflowInstanceStore("connection string");
var handle = InstanceStore.CreateInstanceHandle();
var view = InstanceStore.Execute(
handle,
new CreateWorkflowOwnerCommand(),
TimeSpan.FromSeconds(5));
handle.Free();
InstanceStore.DefaultInstanceOwner = view.InstanceOwner;
}
static void CreateWorkflowApp()
{
WfApp = new WorkflowApplication(Activity)
{
InstanceStore = InstanceStore,
};
WfApp.PersistableIdle = (e) => { return PersistableIdleAction.Unload; }
WfApp.Unloaded = (e) =>
{
Console.WriteLine("WF App Unloaded\n");
unloadEvent.Set();
};
WfApp.Completed = (e) =>
{
Console.WriteLine("\nWF App Ended: {0}.", e.CompletionState);
};
}
static Activity GetExampleActivity()
{
var response = new Variable<string>();
return return new Sequence()
{
Variables = { response },
Activities =
{
new WriteLine()
{
Text = new InArgument<string>("Type some word:")
},
new ReadLine()
{
BookmarkName = READ_LINE_BOOKMARK,
Result = new OutArgument<string>(response)
},
new WriteLine()
{
Text = new InArgument<string>((context) => "You've typed: " + response.Get(context))
}
}
};
}
そうは言っても、IIS と AppFabric の使用を検討してください。後悔することはありません。AppFabric は、数回クリックするだけで、WF 内に実装するのに骨の折れる作業のうち 2 つ (持続性と監視) を処理します。このパスを選択した場合、次のコードを記述する必要はありません。
ワークフローを WCF アプリケーションとして展開し、他の WCF コントラクトとして呼び出すだけです。受信アクティビティ (時間がかかりすぎる場合に待機して持続するもの) であるOperationContractsと、対応する送信アクティビティ (クライアントに値を返すもの) があります。それらの間の相関の概念さえあります。AppFabric は、以前に初期化された関連付けハンドルを渡すだけで、ワークフローの再開を処理します。
AppFabric は、永続ストア、監視、およびアイドル状態や永続状態になるまでの時間などのその他のオプションを構成するための構成 UI を提供します。
Active/Idle/Suspended ワークフロー、監視データなどを可視化できます。