Duplex Workflow Service 샘플
이 샘플에서는 두 개의 통신 서비스 간에 비동기 이중 통신을 수행하는 방법을 보여 줍니다. 또한 메시지를 사용하여 localhost와 워크플로 간의 통신을 수행하는 방법도 보여 줍니다. 양방향으로 통신이 수행될 수 있으려면 두 서비스 간에 이중 통신을 실행하는 동안 먼저 두 서비스가 컨텍스트를 교환해야 합니다. 통신을 시작한 서비스는 해당 메시지에 대한 회신에서 컨텍스트를 수신합니다. 수신 서비스에서 시작 서비스로의 통신을 지원하기 위해 시작 서비스는 첫 번째 메시지에서 해당 컨텍스트 정보를 보내야 합니다.
참고
이 샘플을 빌드하고 실행하려면 .NET Framework 버전 3.5가 설치되어 있어야 하며 프로젝트 및 솔루션 파일을 열려면 Visual Studio 2008이 필요합니다.
이 샘플 설정에 대한 자세한 내용은 Windows Communication Foundation 샘플의 일회 설치 절차를 참조하십시오.
메시지는 또한 localhost와 서비스 간의 통신에 사용됩니다. localhost는 서비스가 콜백하는 데 사용할 수 있는 잘 알려진 끝점을 노출합니다. 이 샘플에서는 호스팅된 서비스를 위한 워크플로 서비스 호스트뿐만 아니라 로컬 수신기를 만들기 위한 기능을 제공하는 LocalWorkflowServiceHost
형식을 구현합니다.
이 샘플에는 다음 통신 엔터티가 포함되어 있습니다.
클라이언트 호스트
클라이언트 호스트는IReverseContract
에서 작업을 호출하여 클라이언트 워크플로와 통신합니다. 클라이언트 호스트가BeginWork
작업을 처음 호출할 때 클라이언트 워크플로가 만들어집니다. 클라이언트 워크플로는BeginWork
작업에 응답하여 클라이언트 워크플로에 대한 컨텍스트가 포함된 메시지를 다시 보냅니다. 호스트가 클라이언트 워크플로와 통신하기 위해 만든 채널은 이제 추가 통신을 위한 컨텍스트를 가집니다. 이 샘플에서는 클라이언트 호스트가 동일한 채널을 사용하여 여러 작업 항목을 클라이언트 워크플로에 보내는 방법을 보여 줍니다.
워크플로가 클라이언트 호스트와 통신할 수 있도록 클라이언트 호스트에는 수신 대기하는 잘 알려진 끝점이 있습니다. 이 샘플에서 잘 알려진 이 끝점의 이름은HostEndPoint
입니다. 클라이언트 워크플로에 대한 워크플로 서비스 호스트뿐만 아니라 클라이언트 호스트에 대한 잘 알려진 이 끝점을 만들기 위해LocalWorkflowServiceHost
가 사용됩니다.LocalWorkflowServiceHost localHost = new LocalWorkflowServiceHost(typeof(ClientWorkflow),new ClientHost()); localHost.WorkflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e) { Console.WriteLine("WorkflowTerminated: " + e.Exception.Message); }; localHost.WorkflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { Console.WriteLine("WorkflowCompleted: " + e.WorkflowInstance.InstanceId.ToString()); }; localHost.Open();
클라이언트 워크플로(서비스로 노출됨)
클라이언트 워크플로는IReverseContract
를 구현합니다. 위의 그림에 나온 것처럼 서비스 워크플로는 이것을 사용하여 클라이언트 워크플로와 통신합니다. 먼저 클라이언트 워크플로는 서비스 워크플로를 만드는BeginWorkflow
작업을 호출합니다. 회신은 서비스 워크플로에 대한 후속 클라이언트 워크플로 통신에서 사용되는 서비스 워크플로에 대한 컨텍스트를 반환합니다.BeginWorkflow
작업의 일부로 클라이언트 워크플로는 끝점 주소뿐만 아니라 서비스 워크플로에 대한 컨텍스트 헤더를 포함하는 고유한 끝점 참조를 전달합니다. 서비스 워크플로는 이 끝점 주소를 사용하여 클라이언트 워크플로와 비동기적으로 통신합니다.
초기 상태의WaitForBeginWork
이벤트 처리기는DoSetReturnAddress
라는 코드 동작을 구현합니다. 이 동작은 다음 샘플과 같이 서비스 워크플로에 보내지는 끝점 참조를 설정합니다.private void SetReturnAddress(object sender, EventArgs e) { EndpointAddress epr = ContextManager.CreateEndpointAddress(ReturnUri, this.ReceiveWorkItemComplete); ReturnAddress = EndpointAddress10.FromEndpointAddress(epr); DebugOutput("[ClientWorkflow:SetReturnAddress] " + epr.Headers[0].GetValue<string>()); }
서비스 호스트
이 샘플에서는 워크플로 서비스 호스트를 구현합니다. 이 서비스 호스트는 클라이언트로부터 요청을 수신 대기하는 수신기를 엽니다. 클라이언트의 첫 번째 요청은 서비스 워크플로의 인스턴스를 만듭니다. 요청에서 메시지 헤더에 컨텍스트가 포함되어 있으므로 모든 후속 요청은 동일한 워크플로 인스턴스에 라우트됩니다.서비스 워크플로(서비스로 노출됨)
서비스 워크플로는IForwardContract
를 구현합니다.BeginWorkflow
작업의 서비스 워크플로는 클라이언트 워크플로에 대한 끝점 참조를 수신합니다. 서비스 워크플로는 메시지를 클라이언트 워크플로에 비동기적으로 보내는 Send 동작에 해당 끝점 참조를 적용합니다.WaitForBeginWorkflow
이벤트 처리기는BeginWorkflow
수신 동작을 제공합니다. 수신 동작 안에는 다음 코드와 같이 보내기 동작의 반환 주소를 사용하여 메시지를 클라이언트 워크플로에 보내는ApplyReturnAddress
라는 코드 동작이 있습니다.private void ApplyReturnAddress(object sender, EventArgs e) { // apply ReturnAddress to ReverseEndpoint EndpointAddress epr = ReturnAddress.ToEndpointAddress(); ContextManager.ApplyEndpointAddress( this.SendWorkItemComplete, epr); DebugOutput("[ServiceWorkflow:ApplyReturnAddress] " + epr.Headers[0].GetValue<string>()); }
LocalWorkflowServiceHost
클래스는 호스트와 워크플로 간의 통신을 위해 필요한 인프라를 만듭니다. 로컬 워크플로 서비스는 다음과 같은 두 개의 주요 작업을 수행합니다.- 호스트가 워크플로에서 메시지를 수신 대기할 수 있도록 로컬 수신기를 만듭니다.
- WorkflowServiceHost를 인스턴스화하여 워크플로에 대한 수신기를 만듭니다.
또한 이 클래스는 워크플로와 통신하는 데 사용되는 컨텍스트를 호스트가 유지 관리할 수 있도록 도우미 함수를 제공합니다. 호스트가 재활용될 경우 이 컨텍스트는 워크플로 인스턴스와 통신하는 데 사용됩니다.
WorkflowServiceUtility 프로젝트는 컨텍스트를 조작하는 데 필요한 모든 도우미 함수를 제공합니다. 채널에서 컨텍스트를 추출하거나 컨텍스트를 채널에 적용하거나 끝점 주소를 보내기 동작에 적용하기 위한 함수가 제공됩니다.
샘플을 설치, 빌드 및 실행하려면
지속성 공급자를 설치하려면 Windows Communication Foundation 샘플의 일회 설치 절차 항목에 있는 CreateStores.cmd 스크립트를 실행합니다.
DuplexWorkflowService 및 WorkflowServiceUtility 폴더가 동일한 부모 폴더에 위치하도록 워크플로 서비스 유틸리티을 다운로드하여 저장합니다.
지속성 공급자를 사용하지 않으려면 App.config 파일에서
<WorkflowRuntime>
섹션을 주석으로 처리합니다.이 샘플에서는 두 개의 지속성 데이터베이스가 사용됩니다. 서비스 워크플로는
NetFx35Samples_ServiceWorkflowStore
를 사용하고 클라이언트는NetFx35Samples_ClientWorkflowStore
를 사용합니다. 이러한 저장소를 SQL Server 또는 SQL Server Express에서 만들 수 있습니다. App.config 파일에 있는 현재 연결 문자열에서는 SQL Server Express를 사용한다고 가정합니다. SQL Server에서 저장소를 만든 경우 App.config 파일에서 연결 문자열을 변경해야 합니다.클라이언트 호스트와 서비스 호스트가 실행 중이면 콘솔 창에서 Y를 눌러 작업 항목을 처리합니다. 처리를 위해 여러 작업 항목을 보낼 수 있습니다. 클라이언트를 종료했다가 다시 시작하면 중지했던 위치에서 다시 시작됩니다.
서비스의 지속성을 테스트하려면 클라이언트 및 서비스 응용 프로그램을 모두 종료하고 클라이언트 응용 프로그램을 다시 시작한 다음 서비스 응용 프로그램을 다시 시작합니다. 서비스 워크플로가 실행되자마자 클라이언트에 다시 메시지를 보내려고 하기 때문에 이것은 시퀀싱을 위한 것입니다. 클라이언트를 사용할 수 없는 경우 예외가 발생합니다.
클라이언트에서 컨텍스트는 Client.ctx 파일에 저장됩니다. 이 파일은 샘플의 \bin 디렉터리에 저장됩니다. 클라이언트를 다시 열면 클라이언트에서 파일이 있는지 여부를 확인합니다. 파일이 있을 경우 저장된 컨텍스트가 만드는 중인 채널에 적용됩니다. 워크플로 서비스가 완료된 다음에 여전히 \bin 디렉터리에 있는 Client.ctx 파일을 사용하여 클라이언트를 열면 클라이언트는 컨텍스트를 채널에 적용하려고 합니다. 통신하려는 워크플로 인스턴스가 해당 파일에 없기 때문에 이 경우 오류가 발생합니다. 파일을 삭제하고 다시 시도합니다.
Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.