2012-10-19 74 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间歇超时问题。

我只是想确保明智的设计这不是一个问题,即打开一个线程上的服务和处理它?

编辑:

代理内部建立与上为每个线程不同的端点定义绑定的信道。

+0

这是一个有点混乱,你说话“服务”的,我所期待的“代理”(甚至“客户”),例如“线程打开服务”应该是“线程为我的服务打开代理”,对吗? – Jeroen

+0

对不起,我只是更新了问题,所以基本上我的服务已经打开,但是代理只是调用proxy.Channel.StartWork(工作负载);那个特定的服务(已经是自己托管的) - 有意义吗? –

+0

你可能想在你的try-catch子句中加上'finally'。最终即使抛出异常也会执行代码。关于你的问题,我不确定。我也相信把你的绑定传递给构造函数是明智的。这可能是超时异常的原因。 –

回答

6

我认为问题可能在于您没有正确关闭代理服务器。如果你有很多线程打到服务器上,并且他们并不都清理完毕,你可能会在这些连接上出现超时。

处理对于关闭连接并不理想。点击此处了解详情:Disposing proxies

的理想模式使用如下:

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

您尝试关闭连接,如果失败,则中止所有连接。如果发生异常,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