이 항목에서는 채널에 있는 상태 및 전환, 채널 상태를 구성하는 데 사용되는 형식 및 이를 구현하는 방법에 대해 설명합니다.
상태 컴퓨터 및 채널
통신을 처리하는 개체(예: 소켓)는 일반적으로 상태 전환이 네트워크 리소스 할당, 연결 만들기 또는 수락, 연결 닫기 및 통신 종료와 관련된 상태 머신을 제공합니다. 채널 상태 컴퓨터는 해당 개체의 기본 구현을 추상화 하는 통신 개체의 상태의 균일 한 모델을 제공 합니다. 인터페이스는 ICommunicationObject 상태, 상태 전환 메서드 및 상태 전환 이벤트 집합을 제공합니다. 모든 채널, 채널 팩터리 및 채널 수신기는 채널 상태 컴퓨터를 구현합니다.
상태 전환이 발생한 후 외부 관찰자에게 닫힘, 닫기, 오류, 열기 및 열기 이벤트가 발생합니다.
메서드 Abort, Close 및 Open(및 해당 비동기 등가물)은 상태 전환을 야기합니다.
state 속성은 다음에서 정의한 CommunicationState대로 현재 상태를 반환합니다.
ICommunicationObject, CommunicationObject 및 상태 및 상태 전환 사항
생성된 상태에서 시작하여 다양한 속성을 구성할 수 있습니다. 열린 상태에서는 메시지를 보내고 받는 데 개체를 사용할 수 있지만 해당 속성은 변경할 수 없는 것으로 간주됩니다. 종료 상태가 되면 개체는 더 이상 새 보내기 또는 수신 요청을 처리할 수 없지만, 닫기 시간 제한에 도달할 때까지 기존 요청을 완료할 수 있습니다. 복구할 수 없는 오류가 발생하면 개체는 오류에 대한 정보를 검사하고 최종적으로 닫을 수 있는 오류 상태로 전환됩니다. Closed 상태인 경우 개체가 사실상 상태 기계의 끝에 도달했습니다. 개체가 한 상태에서 다음 상태로 전환되면 이전 상태로 돌아가지 않습니다.
다음 다이어그램은 ICommunicationObject 상태 및 상태 전환을 보여 줍니다. 상태 전환은 중단, 열기 또는 닫기라는 세 가지 방법 중 하나를 호출하여 발생할 수 있습니다. 다른 구현 관련 메서드를 호출하여 발생할 수도 있습니다. 오류 상태로의 전환은 통신 개체를 여는 동안 또는 연 후 오류로 인해 발생할 수 있습니다.
모든 ICommunicationObject는 생성된 상태에서 시작합니다. 이 상태에서 애플리케이션은 해당 속성을 설정하여 개체를 구성할 수 있습니다. 개체가 Created가 아닌 다른 상태에 있으면 변경할 수 없는 것으로 간주됩니다.
그림 1 ICommunicationObject 상태 컴퓨터입니다.
WCF(Windows Communication Foundation)는 CommunicationObject을 구현하는 추상 기본 클래스 ICommunicationObject와 채널 상태 기계를 제공합니다. 다음 그래픽은 CommunicationObject에 맞게 수정된 상태 다이어그램입니다. 상태 컴퓨터 외에도 ICommunicationObject 추가 CommunicationObject 메서드가 호출되는 시기를 보여 줍니다.
그림 2. 이벤트 및 보호된 메서드에 대한 호출을 포함하여 ICommunicationObject 상태 머신의 CommunicationObject 구현입니다.
ICommunicationObject 이벤트
CommunicationObject 에서 정의 ICommunicationObject한 5개의 이벤트를 노출합니다. 이러한 이벤트는 상태 전환에 대한 알림을 받을 통신 개체를 사용하는 코드를 위해 설계되었습니다. 위의 그림 2에 표시된 것처럼 개체의 상태가 이벤트에서 명명된 상태로 전환된 후 각 이벤트가 한 번 발생합니다. 5개 EventHandler
이벤트는 모두 다음과 같이 정의된 형식입니다.
public delegate void EventHandler(object sender, EventArgs e);
CommunicationObject 구현에서 발신자는 CommunicationObject 자체이거나, 생성자 오버로드가 사용된 경우 CommunicationObject 생성자로 전달된 발신자입니다. EventArgs 매개 변수는 e
항상 EventArgs.Empty
.입니다.
파생 오브젝트 콜백
5개의 이벤트 CommunicationObject 외에도 상태 전환 전후에 파생 개체를 다시 호출할 수 있도록 설계된 8개의 보호된 가상 메서드를 선언합니다.
CommunicationObject.Open 및 CommunicationObject.Close 메서드 각각에는 세 가지 콜백이 연결되어 있습니다. 예를 들어 CommunicationObject.Open에 해당하는 것은 CommunicationObject.OnOpening, CommunicationObject.OnOpen, 및 CommunicationObject.OnOpened입니다. CommunicationObject.Close에 연결된 메서드는 CommunicationObject.OnClose, CommunicationObject.OnClosing, 그리고 CommunicationObject.OnClosed입니다.
마찬가지로, CommunicationObject.Abort 메서드에는 CommunicationObject.OnAbort가 있습니다.
CommunicationObject.OnOpen는 CommunicationObject.OnCloseCommunicationObject.OnAbort 기본 구현이 없지만 다른 콜백에는 상태 시스템 정확성에 필요한 기본 구현이 있습니다. 이러한 메서드를 재정의하는 경우 기본 구현을 호출하거나 올바르게 바꿔야 합니다.
CommunicationObject.OnOpening, CommunicationObject.OnClosing 및 CommunicationObject.OnFaulted는 각각 해당하는 CommunicationObject.Opening, CommunicationObject.Closing 및 CommunicationObject.Faulted 이벤트를 실행합니다. CommunicationObject.OnOpened 개체 CommunicationObject.OnClosed 상태를 각각 Opened 및 Closed로 설정한 다음 해당 CommunicationObject.Opened 이벤트와 CommunicationObject.Closed 이벤트를 실행합니다.
상태 전환 방법
CommunicationObject 는 중단, 닫기 및 열기 구현을 제공합니다. 또한 오류가 발생한 상태로 상태가 전환되는 Fault 메서드를 제공합니다. 그림 2는 각 전환의 원인이 되는 메서드에 의해 레이블이 지정된 상태 머신을 보여 ICommunicationObject 줍니다(레이블이 지정되지 않은 전환은 마지막 레이블이 지정된 전환을 발생시킨 메서드의 구현 내에서 발생).
비고
통신 상태의 모든 CommunicationObject 구현에서 상태 가져오기/설정은 스레드로 동기화됩니다.
생성자
CommunicationObject 는 개체를 만든 상태로 두는 세 개의 생성자를 제공합니다. 생성자는 다음과 같이 정의됩니다.
첫 번째 생성자는 개체를 사용하는 생성자 오버로드에 위임하는 매개 변수가 없는 생성자입니다.
protected CommunicationObject() : this(new object()) { … }
개체를 매개변수로 받는 생성자는 통신 개체 상태에 대한 액세스를 동기화할 때 그 매개변수를 잠금에 사용하는 개체로 사용합니다.
protected CommunicationObject(object mutex) { … }
마지막으로, 세 번째 생성자는 이벤트가 발생할 때 ICommunicationObject 보낸 사람 인수로 사용되는 추가 매개 변수를 받습니다.
protected CommunicationObject(object mutex, object eventSender) { … }
이전 두 생성자는 발신자를 이것으로 설정합니다.
Open 메서드
전제 조건: 상태가 생성됨.
사후 조건: 상태가 열려 있거나 오류가 발생합니다. 예외를 발생시킬 수 있습니다.
Open() 메서드는 통신 개체를 열고 상태를 Opened로 설정하려고 합니다. 오류가 발생하면 상태를 Faulted로 설정합니다.
메서드는 먼저 현재 상태가 Created인지 확인합니다. 현재 상태가 '열림 중' 또는 '열림'이라면 InvalidOperationException을 throw합니다. 현재 상태가 Closing 또는 Closed이면 개체가 종료된 경우 CommunicationObjectAbortedException을(를) throw하며, 그렇지 않으면 ObjectDisposedException을(를) throw합니다. 현재 상태가 Faulted이면 CommunicationObjectFaultedException을(를) 던집니다.
그런 다음 상태를 Opening으로 설정하고 OnOpening()(Opening 이벤트 발생), OnOpen() 및 OnOpened()을 해당 순서대로 호출합니다. OnOpened()은 상태를 Opened로 설정하고 Opened 이벤트를 발생합니다. 이 중 하나라도 예외가 발생하면, Open()이 Fault()를 호출하고 예외가 전파될 수 있도록 합니다. 다음 다이어그램에서는 Open 프로세스를 자세히 보여줍니다.
내부 통신 개체를 여는 것과 같은 사용자 지정 열기 논리를 구현하도록 OnOpen 메서드를 재정의합니다.
닫기 메서드
전제 조건: 없음.
사후 조건: 상태가 닫힘. 예외를 발생시킬 수 있습니다.
Close() 메서드는 모든 상태에서 호출할 수 있습니다. 개체를 정상적으로 닫으려고 시도합니다. 오류가 발생하면 개체가 종료됩니다. 현재 상태가 Closing 또는 Closed인 경우 메서드는 아무 것도 수행하지 않습니다. 그렇지 않으면 상태를 Closing으로 설정합니다. 원래 상태가 Created, Opening 또는 Faulted이면 Abort()를 호출합니다(다음 다이어그램 참조). 원래 상태가 Opened인 경우, OnClosing()(이는 Closing 이벤트를 발생시킴), OnClose() 및 OnClosed()를 순서대로 호출합니다. 이런 항목들 중 하나가 예외를 발생시키는 경우, Close()는 Abort()를 호출하고, 예외가 전파되도록 합니다. OnClosed()은 상태를 Closed로 설정하고 Closed 이벤트를 발생합니다. 다음 다이어그램에서는 닫기 프로세스를 자세히 보여줍니다.
내부 통신 개체를 닫는 것과 같은 사용자 지정 닫기 논리를 구현하도록 OnClose 메서드를 재정의합니다. 시간 제한 매개 변수가 필요하고 Abort()의 일부로 호출되지 않기 때문에 오랜 시간 동안 차단할 수 있는 모든 정상 닫는 논리(예: 다른 쪽이 응답할 때까지 대기)는 OnClose()에서 구현되어야 합니다.
중지
전제 조건: 없음.
사후 조건: 상태가 닫힘. 예외를 발생시킬 수 있습니다.
Abort() 메서드는 현재 상태가 Closed이거나 개체가 이전에 종료된 경우(예: Abort()가 다른 스레드에서 실행되는 경우) 아무 작업도 수행하지 않습니다. 그렇지 않으면 상태를 Closing으로 설정하고 OnClosing() (Closing 이벤트를 발생시키는), OnAbort() 및 OnClosed()를 해당 순서대로 호출합니다(개체가 종료되고 닫히지 않고 종료되기 때문에 OnClose를 호출하지 않음). OnClosed()은 상태를 Closed로 설정하고 Closed 이벤트를 발생합니다. 이러한 예외가 발생하면, Abort 함수의 호출자에게 다시 전달됩니다. OnClosing(), OnClosed() 및 OnAbort()의 구현은 차단해서는 안 됩니다(예: 입력/출력). 다음 다이어그램에서는 중단 프로세스를 자세히 보여 있습니다.
내부 통신 개체를 종료하는 것과 같은 사용자 지정 종료 논리를 구현하도록 OnAbort 메서드를 재정의합니다.
오류
Fault 메서드는 CommunicationObject에 특화되어 있으며, ICommunicationObject 인터페이스의 일부가 아닙니다. 완전성을 위해 여기에 포함되어 있습니다.
전제 조건: 없음.
사후 조건: 상태가 잘못되었습니다. 예외를 발생시킬 수 있습니다.
현재 상태가 Faulted 또는 Closed인 경우 Fault() 메서드는 아무 작업도 수행하지 않습니다. 그렇지 않으면 상태를 Faulted로 설정하고 OnFaulted()를 호출하여 Faulted 이벤트를 발생합니다. OnFaulted에서 예외를 발생시키면 다시 발생시킵니다.
ThrowIfXxx 메서드
CommunicationObject에는 개체가 특정 상태에 있는 경우 예외를 throw하는 데 사용할 수 있는 세 가지 보호된 메서드가 있습니다.
ThrowIfDisposed 는 상태가 Closing, Closed 또는 Faulted인 경우 예외를 throw합니다.
ThrowIfDisposedOrImmutable 는 상태가 만들어지지 않은 경우 예외를 throw합니다.
ThrowIfDisposedOrNotOpen 는 상태가 열려 있지 않으면 예외를 throw합니다.
상태에 따라 던져지는 예외가 다릅니다. 다음 표는 특정 상태에서 예외를 발생시키는 ThrowIfXxx 메서드를 호출할 때 던져지는 다양한 상태와 해당 예외 유형을 보여 줍니다.
시스템 상태 | 중단이 호출되었나요? | 예외 |
---|---|---|
생성됨 | 해당 없음(N/A) | System.InvalidOperationException |
개시 | 해당 없음(N/A) | System.InvalidOperationException |
시작됨 | 해당 없음(N/A) | System.InvalidOperationException |
결산 | 예 | System.ServiceModel.CommunicationObjectAbortedException |
결산 | 아니오 | System.ObjectDisposedException |
닫힘 | 예 | System.ServiceModel.CommunicationObjectAbortedException 개체가 Abort의 이전의 명시적인 호출로 인해 닫힌 경우 개체에서 Close를 호출할 경우 System.ObjectDisposedException가 throw 됩니다. |
닫힘 | 아니오 | System.ObjectDisposedException |
오류 | 해당 없음(N/A) | System.ServiceModel.CommunicationObjectFaultedException |
타임아웃
앞에서 설명한 몇 가지 메서드는 시간 제한 매개 변수를 사용합니다. Close, Open(특정 오버로드 및 비동기 버전), OnClose 및 OnOpen입니다. 이러한 메서드는 긴 작업(예: 연결을 정상적으로 닫는 동안 입력/출력 차단)을 허용하도록 설계되었기 때문에 시간 제한 매개 변수는 이러한 작업이 중단되기까지 걸리는 시간을 나타냅니다. 이러한 메서드의 구현은 제공된 시간 제한 값을 사용하여 해당 시간 제한 내에 호출자에게 반환되도록 해야 합니다. 시간 제한을 사용하지 않는 다른 메서드의 구현은 긴 작업을 위해 설계되지 않았으며 입력/출력을 차단해서는 안 됩니다.
예외는 제한 시간이 걸리지 않는 Open() 및 Close() 오버로드입니다. 파생 클래스에서 제공하는 기본 시간 제한 값을 사용합니다. CommunicationObject는 두 개의 보호된 추상 속성, 즉 DefaultCloseTimeout로 명명된 것과 DefaultOpenTimeout로 정의된 것을 노출합니다.
protected abstract TimeSpan DefaultCloseTimeout { get; }
protected abstract TimeSpan DefaultOpenTimeout { get; }
파생 클래스는 이러한 속성을 구현하여 시간 제한 값을 사용하지 않는 Open() 및 Close() 오버로드에 대한 기본 시간 제한을 제공합니다. 그런 다음 Open() 및 Close() 구현은 기본 시간 제한 값을 사용하여 오버로드 메서드에 작업을 위임합니다. 예를 들면 다음과 같습니다.
public void Open()
{
this.Open(this.DefaultOpenTimeout);
}
IDefaultCommunicationTimeouts
이 인터페이스에는 열기, 보내기, 받기 및 닫기를 위한 기본 시간 제한 값을 제공하는 4개의 읽기 전용 속성이 있습니다. 각 구현은 적절한 방식으로 기본값을 가져오는 작업을 담당합니다. 편의 ChannelFactoryBaseChannelListenerBase 를 위해 이러한 값의 기본값은 각각 1분입니다.