어댑터 종료 방법
다음 항목에서는 어댑터를 적절하게 종료할 수 있는 지침을 제공합니다.
어댑터 종료
메시징 엔진이 종료되면 IBTTransportControl을 호출합니다. 각 In-Process 어댑터에서 종료 합니다. 이 메서드에서 값이 반환되면 BizTalk Server가 어댑터를 소멸시킵니다. 네이티브 어댑터의 경우에는 이 작업이 즉시 수행되지만 관리되는 어댑터의 경우에는 .NET 가비지 수집 프로세스 때문에 이 작업이 수행되는 정확한 시점을 결정하기 어렵습니다. 어댑터는 Terminate 에서 차단되고 제거될 준비가 될 때까지 필요한 정리 작업을 수행해야 합니다.
Isolated 수신 어댑터 종료
격리된 수신 어댑터는 BizTalk 서비스에서 호스트되지 않으므로 Terminate 가 호출되지 않습니다. 대신 IBTTransportProxy를 호출해야 합니다. TerminateIsolatedReceiver - 메시징 엔진이 종료될 것임을 알립니다.
Marshal.ReleaseComObject를 사용하여 COM 개체 정리
COM 개체를 사용하는 관리되는 코드를 작성할 경우 CLR(공용 언어 런타임)이 COM 개체에 대한 참조를 유지하는 프록시 개체를 생성합니다. 프록시 개체는 가비지 수집의 일반적인 규칙이 적용되는 관리되는 개체입니다. 그러나 가비지 수집기는 .NET 런타임이 할당한 메모리만 확인할 수 있으며 COM 개체를 인식하지 못하기 때문에 문제가 발생합니다. 프록시 개체는 작기 때문에 CLR 가비지 수집기가 이를 인식하지 못하여 큰 COM 개체가 메모리에 남게 될 수 있습니다.
이 문제를 방지하려면 기본 COM 개체, 특히 IBTTransportBatch 개체를 완료할 때 명시적으로 해제합니다. 마샬을 호출하여 이 작업을 수행 합니다. ReleaseComObject.
참고
ReleaseComObject 는 나머지 참조 수를 반환하고 반환된 값이 0인 경우에만 COM 개체를 해제합니다. 개체가 해제되었는지 확인하기 위해 종종 ReleaseComObject 가 루프에서 호출됩니다. 완료된 후에는 완료할 항목이 없으므로 이 개체에서 SuppressFinalize 를 호출해야 합니다. 마지막 단계는 이 개체가 실제로 COM 개체인지 확인하는 것입니다.
다음 코드는 위에서 설명한 프로세스를 보여 줍니다.
if (Marshal.IsComObject (batch))
(
While (0 <Marshal.ReleaseComObject(batch)
;
GC.SuppressFinalize (batch);
GetBatch에서 반환된 IBTTransportBatch 개체를 명시적으로 해제하면 성능이 크게 향상될 수 있습니다.
어댑터를 닫을 때 항상 Terminate 사용
BizTalk Server 코드를 어댑터로 인식하려면 IBTTransportControl이라는 인터페이스를 구현해야 합니다. BizTalk Server가 어댑터와 통신하는 방법을 정의하는 이 인터페이스는 다음과 같이 정의됩니다.
public interface IBTTransportControl
{
void Initialize(IBTTransportProxy transportProxy);
void Terminate();
}
인터페이스에는 Initialize 및 Terminate의 두 가지 메서드가 포함되어 있습니다.
Initialize
BizTalk Server 어댑터 어셈블리를 로드한 후 Initialize 메서드를 호출합니다. 이는 전송 프록시(BizTalk Server에 대한 기본 핸들)를 어댑터에 전달하기 위해서입니다. Initialize 구현은 단순히 전송 프록시를 멤버 변수에 저장합니다.
종료
BizTalk Server 서비스 종료 시 Terminate 메서드를 호출하여 어댑터에 모든 일괄 처리 실행을 완료할 시간을 줍니다. 이렇게 하면 Terminate 메서드의 구현이 훨씬 더 복잡해집니다.
보류 중인 작업이 완료될 때까지 어댑터는 Terminate 호출에서 반환하지 않아야 합니다. BizTalk Server Terminate를 호출하면 어댑터는 현재 작업을 모두 중지하고 새 작업을 시작하지 않아야 합니다.
Terminate는 서비스 종료의 일부로 호출되므로 어댑터가 Terminate에서 영구적으로 차단되면 서비스 제어 관리자가 프로세스를 종료합니다. 이 경우 서비스 제어 관리자가 BizTalk Server 서비스를 중지하게 되므로 경고 메시지가 나타납니다. 가능하면 이와 같은 방식으로 어댑터를 중간에 종료하지 마십시오. 어댑터가 종료 프로세스를 제대로 처리하지 못하고 프로세스 종료를 시작할 때 여전히 실행 중인 스레드가 있는 경우 종료될 때 BizTalk Server에서 액세스 위반 메시지가 나타날 수 있습니다.
BizTalk Server 인터페이스의 비동기 특성 때문에 부하 상태에서는 일괄 처리가 많으며 스레드가 계속 실행되게 됩니다. 계속하기 전에 어댑터가 BizTalk Server 성공적으로 실행된 모든 일괄 처리의 결론을 기다리려면 Terminate 호출을 구현해야 합니다. 일괄 처리의 결론은 BizTalk Server BatchComplete 콜백을 통해 신호를 받습니다. Terminate 호출은 보류 중인 모든 BatchComplete가 발생할 때까지 기다려야 합니다. 이때 일괄 처리 실행은 성공적이어야 합니다. 즉, IBTTransportBatch::Done 에 대한 호출은 실패하지 않아야 합니다. IBTTransportBatch::Done에 대한 호출이 실패하면 일괄 처리 콜백이 없습니다.
어댑터에 동기화 코드를 추가해야 하는 이유를 알고 있다면 비교적 쉽게 코드를 구현할 수 있습니다.
한 가지 간단한 방법은 작업자 스레드에 대한 enter 및 leave 메서드와 스레드가 보호된 실행 내에 있는 동안 차단하는 종료 메서드를 사용하여 복합 동기화 개체를 구현하는 것입니다. (덧붙여, 솔루션은 작업자 스레드를 판독기로 간주하고 종결 메서드를 작성기로 간주할 수 있는 친숙한 다중 판독기 단일 작성기 구조와 매우 유사합니다.)
terminate 메서드는 다음과 같습니다.
void terminate ()
{
this.control.Terminate();
}
각 작업자 스레드에 대해 다음을 구현합니다.
If (!this.control.Enter())
return; // we can’t enter because Terminate has been called
try
{
// create and fill batch
batch.Done();
}
catch (Exception)
{
// we are not expecting a callback
This.control.Leave();
}
BizTalk Server의 콜백에 대해 다음을 구현합니다.
batchComplete (…)
{
// the callback from BizTalk Server
// process results
this.control.Leave();
}
BizTalk Server 여기에 설명된 동기화 메커니즘을 보여 주는 기본 어댑터 샘플의 샘플 코드 ControledTermination.cs와 함께 제공됩니다.