2012-10-19 7 views
5

Ich versuche, einen Proxy für einen Thread (im Hintergrund) zu öffnen, der Thread erstellt eine neue Instanz des Proxy, ruft eine Methode des Dienstes und sofort nach dem Dienst verfügbar.Starten mehrerer Dienste auf Threads

All dies geschieht in einem Thread:

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(); 

Ich halte intermittierende Timeout Probleme zu sehen, passiert, obwohl ich das Timeout auf max für Close eingestellt haben, Opentimeout, ReceiveTimeout, Sendtimeout.

Ich möchte nur sicherstellen, Design-weise ist dies kein Problem, d. H. Einen Dienst auf einem Thread zu öffnen und zu entsorgen?

EDIT:

Proxy stellt intern einen Kanal mit benutzerdefinierten für jeden Thread auf unterschiedlichen Endpunkte zu binden.

+0

Es ist ein wenig verwirrend, dass man von „Service“ sprechen, wo ich erwarten würde „Proxy“ (oder auch „Client“), z.B. "Der Thread öffnet den Dienst" sollte "der Thread öffnet einen Proxy für meinen Dienst", richtig? – Jeroen

+0

Sorry, ich habe gerade die Frage aktualisiert, also im Grunde ist mein Dienst bereits geöffnet, aber ja, der Proxy ruft nur den proxy.Channel.StartWork (workload); von diesem bestimmten Dienst (der bereits selbst gehostet ist) - macht Sinn? –

+0

möchten Sie möglicherweise eine "finally" zu Ihrer try-catch-Klausel hinzufügen. führt schließlich Code aus, obwohl eine Ausnahme ausgelöst wird. In Bezug auf dein Problem bin ich unsicher. Ich glaube auch, dass es klug wäre, Ihre Bindung in den Konstruktor zu übergeben. Dies könnte die Ursache für Ihre Zeitüberschreitungsausnahme sein. –

Antwort

6

Ich denke, das Problem kann darin liegen, dass Sie die Proxies nicht ordnungsgemäß schließen. Wenn Sie viele Threads auf dem Server haben und diese nicht alle selbst aufräumen, können Sie bei diesen Verbindungen Timeouts bekommen.

Dispose ist nicht ideal zum Schließen von Verbindungen. Weitere Informationen hier: Disposing proxies

Das ideale Muster ist wie folgt zu verwenden:

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

Sie versuchen, die Verbindung zu schließen, wenn es fehlschlägt, können Sie alle Verbindungen abzubrechen. Dispose wird nicht abgebrochen, wenn eine Ausnahme vorliegt.

Als solches würde ich wie so Refactoring:

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

Das funktioniert. WCF-Proxys sind jedoch Thread-sicher (gleichzeitige Aufrufe werden serialisiert). Da das Erstellen eines Proxys und das Öffnen einer neuen Verbindung zum Server eine teure Operation ist, werden Proxys normalerweise über Threads wiederverwendet. –

+0

Ich stimme zu, deshalb sollte er idealerweise einen Wiederholungsmechanismus haben, falls die Verbindung aus irgendeinem Grund fehlschlägt. Dieses Muster in der Fehlerbehandlung würde dann sicherstellen, dass die alte Verbindung bereinigt wird, bevor sie gezwungen wird, eine neue zu erstellen. – Bardia