2012-10-19 4 views
5

백그라운드에서 스레드에서 프록시를 열려고 시도하고 스레드가 프록시의 새 인스턴스를 만들고 서비스 메서드를 호출하고 서비스를 삭제 한 직후.스레드에서 여러 서비스 시작

이 모든 스레드에서 발생 :

var background = new Thread(() => 
{ 
    var proxy = new AssignmentSvcProxy(new EndpointAddress(worker.Address));    

    try 
    { 
     proxy.Channel.StartWork(workload); 
     proxy.Dispose();     
    } 
    catch (EndpointNotFoundException ex) 
    { 
     logService.Error(ex);       
     proxy.Dispose(); 
     proxy = null; 
    } 
    catch (CommunicationException ex) 
    { 
     logService.Error(ex); 
     proxy.Dispose(); 
     proxy = null; 
    } 
    catch (TimeoutException ex) 
    { 
     logService.Error(ex);      
     proxy.Dispose(); 
     proxy = null; 
    } 
    catch (Exception ex) 
    { 
     logService.Error(ex);      
     proxy.Dispose(); 
     proxy = null; 
    }     

}) { IsBackground = true }; 

background.Start(); 

은 내가 CloseTimeout, openTimeout의, ReceiveTimeout, SendTimeout에 대한 최대 시간 초과를 설정 한 경우에도 발생하는 간헐적 인 시간 제한 문제를보고 계속.

디자인에 현명한 해결책이 있는지 확인하고 싶습니다. 즉, 스레드에서 서비스를 열어서 삭제하는 것입니다.

EDIT :

프록시는 내부적으로 정의는 각 스레드의 다른 엔드 포인트와 결합 채널을 확립한다.

+0

그것은 내가 "프록시"를 기대하는 위치를 "서비스"말하는 것을 조금 혼란, 예를 들어, "스레드가 서비스를 엽니 다" "스레드가 내 서비스의 프록시를 여는"것이 맞지 않습니까? – Jeroen

+0

죄송합니다. 질문을 업데이트 했으므로 기본적으로 내 서비스는 이미 열려 있지만 프록시는 단지 proxy.Channel.StartWork (작업 부하)를 호출합니다. 그 특정 서비스 (이미 자체 호스팅)의 - 이해가 되니? –

+0

try-catch 절에'finally'를 추가 할 수 있습니다. 예외가 발생하더라도 코드를 마지막으로 실행합니다. 당신의 이슈에 관해서, 나는 불확실합니다. 나는 또한 당신의 바인딩을 생성자에 전달하는 것이 현명 할 것이라고 믿는다. 이것은 타임 아웃 예외의 원인 일 수 있습니다. –

답변

6

나는이 문제가 프록시를 제대로 닫지 않는다고 생각할 수 있습니다. 서버에 연결되는 많은 스레드가 있고 자체적으로 정리 작업이 완료되지 않은 경우 해당 연결에서 시간 초과가 발생할 수 있습니다.

처분은 연결을 닫는 데 적합하지 않습니다.

try 
{ 
    proxy.Close(); 
} 
catch (Exception ex) 
{ 
    proxy.Abort(); 
} 
finally 
{ 
    proxy = null; 
} 

당신이 실패하면, 당신은 모든 연결을 중단 연결을 닫으려고 : 여기에 더 많은 정보를 다음과 같이 Disposing proxies

이상적인 패턴을 사용할 수있다. 예외가 있으면 Dispose가 중단되지 않습니다. 이와 같이

, 내가 지금 같은 리팩토링 것 (또는 "클라이언트")

var background = new Thread(() => 
{ 
    var proxy = new AssignmentSvcProxy(new EndpointAddress(worker.Address));    

    try 
    { 
     proxy.Channel.StartWork(workload); 
    } 
    catch (Exception ex) 
    { 
     // You aren't doing anything special with your specific exception types 
     logService.Error(ex);      
    }     
    finally 
    { 
     try 
     { 
      proxy.Close(); 
     } 
     catch (Exception ex) 
     { 
      proxy.Abort(); 
     } 
     finally 
     { 
      proxy = null; 
     } 
    } 

}) { IsBackground = true }; 

background.Start(); 
+1

이것은 작동합니다. 그러나 WCF 프록시는 스레드로부터 안전합니다 (동시 호출이 직렬화됩니다). 프록시를 만들고 서버에 대한 새 연결을 여는 작업은 비용이 많이 드는 작업이므로 일반적으로 프록시는 스레드간에 재사용됩니다. –

+0

나는 어떤 이유에서든 연결이 실패 할 경우를 대비하여 이상적으로 재시도 메커니즘을 가져야하는 이유에 동의합니다. 그런 다음 실패 처리에서의이 패턴은 새로운 연결을 강제로 생성하기 전에 이전 연결이 정리되도록합니다. – Bardia