【问题标题】:Starting multiple services on threads在线程上启动多个服务
【发布时间】:2012-10-19 15:30:16
【问题描述】:

我正在尝试在线程上(在后台)打开代理,该线程创建代理的新实例,调用服务的方法并立即处理服务。

所有这些都发生在一个线程上:

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 的超时设置为最大值,我仍然会看到间歇性超时问题。

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

编辑:

代理在内部为每个线程在不同端点上建立一个自定义绑定的通道。

【问题讨论】:

  • 您在我期望“代理”(甚至“客户端”)的地方谈到“服务”有点令人困惑,例如“线程打开服务”应该是“线程为我的服务打开代理”吧?
  • 对不起,我刚刚更新了这个问题,所以基本上我的服务已经打开了,但是代理只是调用了 proxy.Channel.StartWork(workload);那个特定的服务(已经是自托管的)——有意义吗?
  • 您可能希望在 try-catch 子句中添加 finally。即使抛出异常,finally 也会执行代码。关于你的问题,我不确定。我也相信将绑定传递给构造函数是明智的。这可能是您的超时异常的原因。
  • 你启动了多少这些线程?还是只有这个?
  • 为什么要给自己纺线?我会选择异步方法或 TPL

标签: c# multithreading wcf socket-timeout-exception


【解决方案1】:

我认为问题可能在于您没有正确关闭代理。如果您有很多线程访问服务器,并且它们自己并没有全部清理干净,那么您可能会在这些连接上遇到一些超时。

Dispose 不适合关闭连接。更多信息在这里: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();

【讨论】:

  • 这行得通。但是,WCF 代理是线程安全的(并发调用是序列化的)。由于创建代理并打开与服务器的新连接是一项昂贵的操作,因此通常会跨线程重用代理。
  • 我同意,这就是为什么他应该有一个理想的重试机制,以防连接因任何原因而失败。故障处理中的这种模式将确保在强制创建新连接之前清理旧连接。
猜你喜欢
  • 1970-01-01
  • 2012-01-21
  • 1970-01-01
  • 2018-04-12
  • 2017-05-15
  • 2014-09-28
  • 2021-09-10
  • 2012-03-21
  • 1970-01-01
相关资源
最近更新 更多