클라이언트에서 콜백 메서드를 호출하는 WCF 서비스에 문제가 발생했습니다. 먼저 서비스 :WCF 콜백 교착 상태
[ServiceContract(
SessionMode = SessionMode.Required,
CallbackContract = typeof(IMarketObserver))]
public interface IServer
{
...
[OperationContract]
[FaultContractAttribute(typeof(WCFFaultDetail))]
bool NotifyOnMarket(EnumMarkets marketID);
...
}
서비스 구현 :
이[ServiceBehavior(
InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple,
UseSynchronizationContext = false)]
public sealed class Platform : IServer
{
...
public bool NotifyOnMarket(EnumMarkets marketID)
{
try
{
IMarketObserver callback = OperationContext.Current.GetCallbackChannel<IMarketObserver>();
if (subscribers.Contains(callback) == false)
{
subscribers.Add(callback);
}
}
catch
{
return false;
}
//This call may cause a call to the callback method SendMarketData()!!
callSomeMethod();
return exchangeProxy.IsMarketIDValid();
}
콜백 계약 :
public interface IMarketObserver
{
[OperationContract(IsOneWay = true)]
void SendMarketData(MarketData marketData);
}
이 콜백의 클라이언트 구현은이 :
이[CallbackBehavior(
ConcurrencyMode = ConcurrencyMode.Multiple,
UseSynchronizationContext = false)]
public class MarketBase :
IServerCallback
{
protected IService serviceProxy;
public void SendMarketData(MarketData marketData)
{
//Do something
}
private void NotifyOnMarkets()
{
foreach (EnumMarkets item in observedMarkets)
{
try
{
bool res = serviceProxy.NotifyOnMarket(item);
}
catch (Exception e)
{
...
}
}
}
문제가 발생합니다 때 c foreach 루프를 사용하여 NotifyOnMarkets()를 호출합니다.
obserasedMarkets 목록에 하나의 항목 만있는 경우 서비스의 NotifyOnMarket() 메소드에 대한 호출이 정확히 하나이므로 모든 것이 올바르게 작동합니다.
그러나 관찰 된 MarketSet에 둘 이상의 항목이 포함되어 있으면 NotifyOnMarket()이 서버에 빈번하게 자주 호출됩니다.
서버에서 NotifyOnMarket()을 구현하면 메서드를 호출하여 콜백 메서드 인 SendMarketData를 호출합니다 (이 사실을 알았습니다).
추적에서 볼 수있는 그 serviceProxy.NotifyOnMarket (item); 두 번째 항목으로 돌아 오지 않으면 시간 초과가 발생합니다.
서버 측에서는 NotifyOnMarket()에 대한 다중 호출이 올바르게 처리되고 메서드가 종료됩니다. 그러나 위에서 언급했듯이 부울 결과는 클라이언트에 표시되지 않습니다 (시간 초과).
또한 서버 측에서 콜백이 호출 됨 (단방향이므로 응답이 반환되지 않음)을 볼 수 있지만 클라이언트 측에서는 콜백 구현이 호출되지 않기 때문에 아무 일도 발생하지 않습니다.
필자의 결론은 일종의 교착 상태가 발생했으며 이는 클라이언트 인스턴스가 잠겨서 서버가 콜백 메소드를 호출 할 수 없기 때문일 수 있습니다.
서비스 호출을 수행하는 클래스에서 인스턴스 컨텍스트 클래스를 분리하는 것이 더 좋습니까? 그렇다면 왜? 조언을
감사합니다,
위르겐 질문에 대한
링크의 Thx. 내 콜백 구현에서 볼 수 있듯이 ConcurrencyMode를 여러 개로 설정했습니다 (또한 Reentrant를 시도했습니다). 이렇게하면 여러 스레드가있는 클라이언트에서 여러 호출을 허용해야합니다. ConcurrencyMode는 WCF에게 자신을 위해 동기화를 수행 할 것임을 알리는 유일한 문이어야합니다. 그러나 이것은 내 대답의 블로그 게시물 링크에서 볼 수있는 것처럼 일을하지 않습니다. ConcurrencyMode = ConcurrencyMode.Multiple이면 충분합니다. ThreadPool을 사용하는 것은 논리적 솔루션이 아닙니다. – Juergen
서비스 구현 클래스에서 [ServiceBehavior (ConcurrencyMode = ConcurrencyMode.Reentrant)]를 추가했을 때만 비슷한 문제가 발생했습니다. 콜백 클래스에 넣을 때 작동하지 않습니다. – Jonathan
그래서 해결책은 무엇입니까? 나는 이것이 수년 전 이었음을 안다. 그러나 그것은 여전히 다른 사람들에게 가치있는 정보이다. 나는 당신의 코드가 작동 할 것이라고 생각했을 것이다. 그리고 그것을 "re-entrant"로 바꾸면 문제가 해결되지 않을 것이다. 나는 당신의 테스트를 복제하고 11 월에 버그가 있었는지 지금은 고쳐 졌는지에 유혹을 받는다. –