방법: 워크플로 실행
이 항목에서는 Windows Workflow Foundation 초보자를 위한 자습서에 포함된 일련의 항목 중 하나로, 워크플로 호스트를 만들고 이전 How to: Create a Workflow 항목에서 정의한 워크플로를 실행하는 방법을 설명합니다.
참고 항목
초보자를 위한 자습서의 각 항목은 이전 항목을 바탕으로 합니다. 이 항목을 진행하려면 먼저 How to: Create an Activity 및 How to: Create a Workflow를 완료해야 합니다.
워크플로 호스트 프로젝트를 만들려면
Visual Studio 2012를 사용하여 이전 방법: 활동 만들기 토픽의 솔루션을 엽니다.
솔루션 탐색기 에서 WF45GettingStartedTutorial 솔루션을 마우스 오른쪽 단추로 클릭하고 추가, 새 프로젝트를 차례로 선택합니다.
팁
솔루션 탐색기 창이 표시되어 있지 않으면 보기 메뉴에서 솔루션 탐색기 를 선택합니다.
설치됨 노드에서 Visual C#, 워크플로 (또는 Visual Basic, 워크플로)를 차례로 선택합니다.
참고 항목
설치됨 노드의 다른 언어 노드 아래에는 Visual Studio에서 기본 언어로 구성된 프로그래밍 언어에 따라 Visual C# 또는 Visual Basic 노드가 표시될 수 있습니다.
.NET Framework 버전 드롭다운 목록에서 .NET Framework 4.5 가 선택되어 있는지 확인합니다. 워크플로 목록에서 워크플로 콘솔 애플리케이션 을 선택합니다.
NumberGuessWorkflowHost
이름 상자에 를 입력하고 확인을 클릭합니다. 이렇게 하면 기본 워크플로 호스팅 지원이 포함된 시작 워크플로 애플리케이션이 만들어집니다. 이 기본 호스팅 코드를 수정하고 이를 사용하여 워크플로 애플리케이션을 실행합니다.솔루션 탐색기 에서 새로 추가한 NumberGuessWorkflowHost 프로젝트를 마우스 오른쪽 단추로 클릭하고 참조 추가를 선택합니다. 참조 추가 목록에서 솔루션 을 선택하고 NumberGuessWorkflowActivities옆의 확인란을 선택한 다음 확인을 클릭합니다.
솔루션 탐색기 에서 Workflow1.xaml 을 마우스 오른쪽 단추로 클릭하고 삭제를 선택합니다. 확인 을 클릭하여 확인합니다.
워크플로 호스팅 코드를 수정하려면
솔루션 탐색기 에서 Program.cs 또는 Module1.vb 를 두 번 클릭하여 코드를 표시합니다.
팁
솔루션 탐색기 창이 표시되어 있지 않으면 보기 메뉴에서 솔루션 탐색기 를 선택합니다.
이 프로젝트는 워크플로 콘솔 애플리케이션 템플릿을 사용하여 만들었기 때문에 Program.cs 또는 Module1.vb 에 다음과 같은 기본 워크플로 호스팅 코드가 포함되어 있습니다.
' Create and cache the workflow definition. Dim workflow1 As Activity = New Workflow1() WorkflowInvoker.Invoke(workflow1)
// Create and cache the workflow definition. Activity workflow1 = new Workflow1(); WorkflowInvoker.Invoke(workflow1);
이 생성된 호스팅 코드에서는 WorkflowInvoker를 사용합니다. WorkflowInvoker 는 메서드 호출과 같은 방식으로 워크플로를 호출하기 위한 간단한 방법을 제공하며, 지속성을 사용하지 않는 워크플로에만 사용될 수 있습니다. WorkflowApplication 은 수명 주기 이벤트 알림, 실행 제어, 책갈피 다시 시작 및 지속성을 비롯한 다양한 워크플로 실행 모델을 제공합니다. 이 예제에서는 책갈피를 사용하며 WorkflowApplication 을 사용하여 워크플로를 호스트합니다. 기존
using
using 또는 Imports 문 아래의 Program.cs 또는 Module1.vb 위에 다음 또는 Imports 문을 추가합니다.Imports NumberGuessWorkflowActivities Imports System.Threading
using NumberGuessWorkflowActivities; using System.Threading;
WorkflowInvoker 를 사용하는 코드 행을 다음과 같은 기본 WorkflowApplication 호스팅 코드로 바꿉니다. 이 샘플 호스팅 코드는 워크플로를 호스팅 및 호출하기 위한 기본 단계를 보여 주지만 이 항목에서 워크플로를 실행하는 기능은 아직 포함하고 있지 않습니다. 다음 단계에서는 애플리케이션이 완료될 때까지 이 기본 코드를 수정하고 기능을 추가합니다.
참고 항목
이 예제에서
Workflow1
은 이전 방법에서 완료한 워크플로우에 따라FlowchartNumberGuessWorkflow
,SequentialNumberGuessWorkflow
또는StateMachineNumberGuessWorkflow
로 바꿔야 합니다: 워크플로 만들기 단계를 수행합니다.Workflow1
을 바꾸지 않으면 워크플로를 빌드하거나 실행할 때 빌드 오류가 발생합니다.AutoResetEvent syncEvent = new AutoResetEvent(false); WorkflowApplication wfApp = new WorkflowApplication(_wf); wfApp.Completed = delegate (WorkflowApplicationCompletedEventArgs e) { syncEvent.Set(); }; wfApp.Aborted = delegate (WorkflowApplicationAbortedEventArgs e) { Console.WriteLine(e.Reason); syncEvent.Set(); }; wfApp.OnUnhandledException = delegate (WorkflowApplicationUnhandledExceptionEventArgs e) { Console.WriteLine(e.UnhandledException.ToString()); return UnhandledExceptionAction.Terminate; }; wfApp.Run(); syncEvent.WaitOne();
Dim syncEvent As New AutoResetEvent(False) Dim wfApp As New WorkflowApplication(New Workflow1()) wfApp.Completed = Sub(e As WorkflowApplicationCompletedEventArgs) syncEvent.Set() End Sub wfApp.Aborted = Sub(e As WorkflowApplicationAbortedEventArgs) Console.WriteLine(e.Reason) syncEvent.Set() End Sub wfApp.OnUnhandledException = Function(e As WorkflowApplicationUnhandledExceptionEventArgs) Console.WriteLine(e.UnhandledException) Return UnhandledExceptionAction.Terminate End Function wfApp.Run() syncEvent.WaitOne()
이 코드는 WorkflowApplication을 만들고 세 가지 워크플로 수명 주기 이벤트를 구독한 다음 Run을 호출하여 워크플로를 시작하고 워크플로가 완료될 때까지 대기합니다. 워크플로가 완료되면 AutoResetEvent 가 설정되고 호스트 애플리케이션이 완료됩니다.
워크플로의 입력 인수를 설정하려면
Program.cs 또는 Module1.vb 맨 위의 기존
using
또는Imports
문 아래에 다음 문을 추가합니다.새로운 WorkflowApplication 을 만드는 코드 행을 코드 생성 시 매개 변수 사전을 만들어 워크플로에 전달하는 다음 코드로 바꿉니다.
참고 항목
이러한 예제의
Workflow1
을 이전FlowchartNumberGuessWorkflow
,SequentialNumberGuessWorkflow
,StateMachineNumberGuessWorkflow
또는 How to: Create a Workflow 로 바꾸세요.Workflow1
을 바꾸지 않으면 워크플로를 빌드하거나 실행할 때 빌드 오류가 발생합니다.var inputs = new Dictionary<string, object>() { { "MaxNumber", 100 } }; WorkflowApplication wfApp = new(_wf, inputs) {
Dim inputs As New Dictionary(Of String, Object) inputs.Add("MaxNumber", 100) Dim wfApp As New WorkflowApplication(New Workflow1(), inputs)
이 사전에는
MaxNumber
키와 함께 요소 하나가 있습니다. 입력 사전의 키는 워크플로 루트 활동의 입력 인수에 해당합니다.MaxNumber
는 워크플로에서 임의로 생성되는 숫자의 상한을 결정하는 데 사용됩니다.
워크플로의 출력 인수를 검색하려면
Completed 처리기를 수정하여 워크플로에서 사용된 횟수를 검색하고 표시합니다.
Completed = delegate (WorkflowApplicationCompletedEventArgs e) { int Turns = Convert.ToInt32(e.Outputs["Turns"]); Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns); syncEvent.Set(); },
wfApp.Completed = Sub(e As WorkflowApplicationCompletedEventArgs) Dim Turns As Integer = Convert.ToInt32(e.Outputs("Turns")) Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns) syncEvent.Set() End Sub
책갈피를 다시 시작하려면
기존
Main
선언 바로 뒤 AutoResetEvent 메서드 위에 다음 코드를 추가합니다.AutoResetEvent idleEvent = new AutoResetEvent(false);
Dim idleEvent As New AutoResetEvent(False)
Idle 에서 세 개의 기존 워크플로 수명 주기 처리기 바로 아래에 다음
Main
처리기를 추가합니다.Idle = delegate (WorkflowApplicationIdleEventArgs e) { idleEvent.Set(); } };
wfApp.Idle = Sub(e As WorkflowApplicationIdleEventArgs) idleEvent.Set() End Sub
워크플로가 다음 추측을 대기하는 유휴 상태가 될 때마다 이 처리기가 호출되고
idleAction
AutoResetEvent가 설정됩니다. 다음 단계의 코드에서는idleEvent
와syncEvent
를 사용하여 워크플로가 다음 추측을 대기하고 있는지 아니면 완료되었는지를 확인합니다.WaitOne
호출을 제거한 다음, 사용자 입력을 수집하고 Bookmark를 다시 시작하는 코드로 대체합니다.다음 코드 행을 제거합니다.
syncEvent.WaitOne();
syncEvent.WaitOne()
코드 행을 다음 예로 대체합니다.
// Loop until the workflow completes. WaitHandle[] handles = new WaitHandle[] { syncEvent, idleEvent }; while (WaitHandle.WaitAny(handles) != 0) { // Gather the user input and resume the bookmark. bool validEntry = false; while (!validEntry) { if (!Int32.TryParse(Console.ReadLine(), out int Guess)) { Console.WriteLine("Please enter an integer."); } else { validEntry = true; wfApp.ResumeBookmark("EnterGuess", Guess); } } }
' Loop until the workflow completes. Dim waitHandles As WaitHandle() = New WaitHandle() {syncEvent, idleEvent} Do While WaitHandle.WaitAny(waitHandles) <> 0 'Gather the user input and resume the bookmark. Dim validEntry As Boolean = False Do While validEntry = False Dim Guess As Integer If Int32.TryParse(Console.ReadLine(), Guess) = False Then Console.WriteLine("Please enter an integer.") Else validEntry = True wfApp.ResumeBookmark("EnterGuess", Guess) End If Loop Loop
애플리케이션을 빌드하고 실행하려면
솔루션 탐색기 에서 NumberGuessWorkflowHost 를 마우스 오른쪽 단추로 클릭하고 시작 프로젝트로 설정을 선택합니다.
Ctrl+F5를 눌러 애플리케이션을 빌드하고 실행합니다. 가능한 한 적은 횟수로 숫자를 추측해 봅니다.
다른 스타일의 워크플로 중 하나로 애플리케이션을 시도하려면
Workflow1
을 만드는 코드의 WorkflowApplication 을 원하는 워크플로 스타일에 따라FlowchartNumberGuessWorkflow
,SequentialNumberGuessWorkflow
또는StateMachineNumberGuessWorkflow
로 바꿉니다.var inputs = new Dictionary<string, object>() { { "MaxNumber", 100 } }; WorkflowApplication wfApp = new(_wf, inputs) {
Dim inputs As New Dictionary(Of String, Object) inputs.Add("MaxNumber", 100) Dim wfApp As New WorkflowApplication(New Workflow1(), inputs)
워크플로 애플리케이션에 지속성을 추가하는 방법은 다음 항목 How to: Create and Run a Long Running Workflow을 참조하세요.
예시
다음 예는 Main
메서드에 대한 완전한 코드 목록입니다.
참고 항목
이러한 예제의 Workflow1
을 이전 FlowchartNumberGuessWorkflow
, SequentialNumberGuessWorkflow
, StateMachineNumberGuessWorkflow
또는 How to: Create a Workflow 로 바꾸세요. Workflow1
을 바꾸지 않으면 워크플로를 빌드하거나 실행할 때 빌드 오류가 발생합니다.
static void Main(string[] args)
{
AutoResetEvent syncEvent = new AutoResetEvent(false);
AutoResetEvent idleEvent = new AutoResetEvent(false);
var inputs = new Dictionary<string, object>() { { "MaxNumber", 100 } };
WorkflowApplication wfApp = new(_wf, inputs)
{
Completed = delegate (WorkflowApplicationCompletedEventArgs e)
{
int Turns = Convert.ToInt32(e.Outputs["Turns"]);
Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns);
syncEvent.Set();
},
Aborted = delegate (WorkflowApplicationAbortedEventArgs e)
{
Console.WriteLine(e.Reason);
syncEvent.Set();
},
OnUnhandledException = delegate (WorkflowApplicationUnhandledExceptionEventArgs e)
{
Console.WriteLine(e.UnhandledException.ToString());
return UnhandledExceptionAction.Terminate;
},
Idle = delegate (WorkflowApplicationIdleEventArgs e)
{
idleEvent.Set();
}
};
wfApp.Run();
// Loop until the workflow completes.
WaitHandle[] handles = new WaitHandle[] { syncEvent, idleEvent };
while (WaitHandle.WaitAny(handles) != 0)
{
// Gather the user input and resume the bookmark.
bool validEntry = false;
while (!validEntry)
{
if (!Int32.TryParse(Console.ReadLine(), out int Guess))
{
Console.WriteLine("Please enter an integer.");
}
else
{
validEntry = true;
wfApp.ResumeBookmark("EnterGuess", Guess);
}
}
}
}
Sub Main()
Dim syncEvent As New AutoResetEvent(False)
Dim idleEvent As New AutoResetEvent(False)
Dim inputs As New Dictionary(Of String, Object)
inputs.Add("MaxNumber", 100)
Dim wfApp As New WorkflowApplication(New Workflow1(), inputs)
wfApp.Completed =
Sub(e As WorkflowApplicationCompletedEventArgs)
Dim Turns As Integer = Convert.ToInt32(e.Outputs("Turns"))
Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns)
syncEvent.Set()
End Sub
wfApp.Aborted =
Sub(e As WorkflowApplicationAbortedEventArgs)
Console.WriteLine(e.Reason)
syncEvent.Set()
End Sub
wfApp.OnUnhandledException =
Function(e As WorkflowApplicationUnhandledExceptionEventArgs)
Console.WriteLine(e.UnhandledException)
Return UnhandledExceptionAction.Terminate
End Function
wfApp.Idle =
Sub(e As WorkflowApplicationIdleEventArgs)
idleEvent.Set()
End Sub
wfApp.Run()
' Loop until the workflow completes.
Dim waitHandles As WaitHandle() = New WaitHandle() {syncEvent, idleEvent}
Do While WaitHandle.WaitAny(waitHandles) <> 0
'Gather the user input and resume the bookmark.
Dim validEntry As Boolean = False
Do While validEntry = False
Dim Guess As Integer
If Int32.TryParse(Console.ReadLine(), Guess) = False Then
Console.WriteLine("Please enter an integer.")
Else
validEntry = True
wfApp.ResumeBookmark("EnterGuess", Guess)
End If
Loop
Loop
End Sub
참고 항목
.NET