2010-03-29 6 views
1

WCF와 블로킹 문제가있는 것 같습니다.WCF 클라이언트가 여러 개있는 경우 차단 문제가 발생했습니다.

두 명의 사용자가 있으며 각 "net.tcp : // localhost : 32000/SymHost /"와 같은 끝점을 사용하여 net.tcp를 사용하여 WCF 호스트에 노출 된 클래스의 인스턴스를 만들었습니다. 클래스는 PerSession 컨텍스트이고 동시성은 재진입 성입니다. 이 클래스는 true를 곧바로 반환하는 Alive()와 내가 삽입 한 AliveWait (true)를 테스트하기 전에 4 초 동안 Thread.Sleep을 수행하는 두 개의 메서드를 노출합니다.

이제 클라이언트 1이 차단 된 시간 동안 충분히 차단 된 AliveWait()을 호출하지만 클라이언트 2가 자체 인스턴스에서 Alive()를 호출하면 클라이언트 1의 호출이 반환 될 때까지 기다려야합니다. 내가 기대했던 것이 아니겠습니까? 나는 클라이언트 2가 아무 일도 없었던 것처럼 계속 진행할 것이라고 기대 했었을 것인가? 아니면 두 사람이 같은 끝점을 공유하고 있다는 사실과 관련이 있는가?

아무도 무슨 일이 일어나고 있으며 어떻게 클라이언트 2가 자체 인스턴스를 중단없이 호출 할 수 있는지를 설명 할 수 있습니까?

많은 도움을 주셨습니다.

답변

1

나는 그것이 무엇인지 발견 ... 다음과 같습니다! Test 클래스의 ServiceBehaviour에서 UseSynchronizationContext를 false로 설정하는 것을 잊었습니다. 동일한 스레드에서 실행되도록 서비스의 모든 호출을 동기화하는 기본값은 true입니다. 따라서 다른 클라이언트의 후속 호출은 단순히 대기열에 저장됩니다.

0

서비스 클래스를 알려주세요! 당신의 설명에서, 무슨 일이 일어나고 있는지를 말하는 것은 불가능합니다.

아니요 클라이언트 2가 클라이언트 1에 의해 차단 될 것으로 예상됩니다. 세션 당 시나리오에서 두 클라이언트는 각각 완전히 독립적 인 서비스 클래스 인스턴스를 가져야합니다. 이것이 우리가 여기서 다루고있는 코드의 종류를 알아야하는 이유입니다. 일반적으로 그런 종류의 설정에는 아무런 문제가 없어야합니다.

+0

그게 정확히 내가 생각한 것입니다 - 나는 그들의 500 자 제한을 exceeeded 이후 내 질문에 대한 답변으로 코드를 게시하고 있습니다! – Marcel

+0

각 WCF 노출 특성을 살펴 보았습니다. 이제 막 잊어 버렸던 점은 Test 클래스의 ServiceBehaviour에서 UseSynchronizationContext를 false로 설정하는 것이 었습니다. 동일한 스레드에서 실행되도록 서비스에 대한 모든 호출을 동기화하는 기본값은 true입니다. 따라서 다른 클라이언트의 후속 호출은 단순히 대기열에 저장됩니다. – Marcel

0

그건 정확히 내가 생각한 것입니다! 계약 정의

[ServiceContract(CallbackContract = typeof(IAliveCallback))] 
public interface IAlive 
{ 
    [OperationContract] 
    bool Validate(); 

    [OperationContract] 
    string AliveWait(int i); // test test 
} 

- - 내 살아 클래스의 계약을 이행

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)] 
public class Alive : SymHostBase, IAlive 
{ 
    private readonly static string _ID = "Alive"; 
    private static int _MaxAliveWaitSeconds = 5; 

    public bool Validate() 
    { 
     return true; 
    } 

    public string AliveWait(int i) 
    { 
     Thread.Sleep(i * 1000); 
     return string.Format("I waited {0} seconds", i); 
    } 

... 
... 
} 

: 그래서 여기 (복사 및 붙여 넣기 ...의 비트 후) 소스 코드의 일부입니다

- 다음 호스트 응용 프로그램에이

 string s = string.Format("net.tcp://localhost:{0}/Host/", port); 
     Uri tcpAddr = new Uri(s); 
     Uri[] baseAddress = { tcpAddr }; 

     int MaxBuffer = 64;  // 64 Mb 
     int bufferSize = MaxBuffer * 1024 * 1024; // 67108864 

     NetTcpBinding tcpBinding = new NetTcpBinding(SecurityMode.None, true); 
     tcpBinding.MaxBufferPoolSize = bufferSize; // 64 Mb 
     tcpBinding.MaxBufferSize = bufferSize; 
     tcpBinding.MaxReceivedMessageSize = bufferSize; 
     tcpBinding.TransferMode = TransferMode.Buffered; 
     tcpBinding.ReaderQuotas.MaxArrayLength = bufferSize; 
     tcpBinding.ReaderQuotas.MaxBytesPerRead = bufferSize; 
     tcpBinding.ReaderQuotas.MaxStringContentLength = bufferSize; 

     tcpBinding.MaxConnections = 100; 
     //tcpBinding.ReceiveTimeout = new TimeSpan(20, 0, 0); 
     tcpBinding.SendTimeout = new TimeSpan(0, 0, 5);  
     tcpBinding.ReliableSession.Enabled = true; 
     tcpBinding.ReliableSession.InactivityTimeout = new TimeSpan(7, 0, 0, 0); // 7 days 


     _HostAlive = new ServiceHost(typeof(Alive), baseAddress); 
     _HostAlive.AddServiceEndpoint(typeof(IAlive), tcpBinding, "alive");  // tcpBinding 


     ServiceThrottlingBehavior throttle = _HostAlive.Description.Behaviors.Find<ServiceThrottlingBehavior>(); 
     if (throttle == null) 
     { 
      throttle = new ServiceThrottlingBehavior(); 
      host.Description.Behaviors.Add(throttle); 
     } 
     throttle.MaxConcurrentCalls = 1000;   // default 16 
     throttle.MaxConcurrentInstances = 1000;  // default 26 
     throttle.MaxConcurrentSessions = 1000;  // default 10 

     // open the host - bring it into life! 
     host.Open(); 
+0

** 가짜 답변을 게시하는 대신 ** 원래 ** 질문 **을 ** 업데이트 해 주시겠습니까 ?? 감사! –

+0

콜백 계약을 사용 중입니다. 그 콜백에는 무엇이 있고, 누가 그 프록시를 사용하고 있습니까? 그것은 UI 스레드가 콜백 (-> 교착 상태가 실행되는 동안 차단 될 수 있습니다 Winforms 애플 리케이션인가요? – John

+0

OK Marc 다음 번에 질문을 업데이트하겠습니다! John, WPF 앱입니다. 콜백은 일반적으로 사용되지만이 경우에는 전혀 사용되지 않습니다. 나는 두 개의 클라이언트를 가지고있다 - 하나는 타이머를 가지고 있고 반복적으로 인스턴스에 Alive()를 호출하고 '사실'을 되 찾는다. 다른 클라이언트는 이제 AliveWait를 3 초 동안 호출하고 3 초 후 호출이 다시 돌아옵니다.이 클라이언트는 모두 정상입니다. 그러나 타이머의 첫 번째 클라이언트는 두 번째 클라이언트의 호출이 완료 될 때까지 응답되지 않은 세 개의 호출을 해고했습니다. 분명 콜백이 호출되거나 호스트가 아무 것도하지 않습니다! – Marcel