C# WCF回调计时器

C# WCF回调计时器,c#,.net,wcf,C#,.net,Wcf,我有一个托管在Windows服务中的WCF服务。这使用发布-订阅模式将事件发布到多个订阅者。然而,我发现在一段时间的不活动之后,连接失败,我得到的可靠会话出现错误。我试图通过更改非活动超时和接收超时设置来解决这个问题,但没有任何区别。老实说,我快疯了 我看到的一个解决方案是每隔一段时间“ping”所有订户。(例如,超时长度的一半) 设置这样的“ping”的最佳方式是什么?i、 e.如何向服务添加计时器,以及如何让计时器调用ping函数 编辑: 我对ping解决方案不太满意,我想进一步调查一下为什

我有一个托管在Windows服务中的WCF服务。这使用发布-订阅模式将事件发布到多个订阅者。然而,我发现在一段时间的不活动之后,连接失败,我得到的可靠会话出现错误。我试图通过更改非活动超时和接收超时设置来解决这个问题,但没有任何区别。老实说,我快疯了

我看到的一个解决方案是每隔一段时间“ping”所有订户。(例如,超时长度的一半)

设置这样的“ping”的最佳方式是什么?i、 e.如何向服务添加计时器,以及如何让计时器调用ping函数

编辑:

我对ping解决方案不太满意,我想进一步调查一下为什么我的可靠会话一直超时。下面是此服务的绑定配置

服务器app.config

<binding name="WSDualHttpBinding_IError" receiveTimeout="24.20:31:23.6470000">
    <reliableSession inactivityTimeout="24.20:31:23.6470000" />
</binding>
<binding name="WSDualHttpBinding_IError" closeTimeout="00:01:00"
    openTimeout="00:01:00" receiveTimeout="24.20:31:23.6470000"
    sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false"
    hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288"
    maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8"
    useDefaultWebProxy="true">
    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
    <reliableSession ordered="true" inactivityTimeout="24.20:31:23.6470000" />
    <security mode="Message">
        <message clientCredentialType="Windows" negotiateServiceCredential="true"
            algorithmSuite="Default" />
    </security>
</binding>

要实现客户端的ping,您可能需要遵循以下步骤列表:

  • 使用Ping方法扩展回调约定(您应该已经有了回调约定,因为您编写了使用发布-订阅模式的回调约定,不是吗?)

  • 在连接后客户端首先调用的操作中,将对客户端操作上下文的引用存储在集合中:

    List<OperationContext> _clientCtxList = new List<OperationContext>();
    
    void IMyService.InitSession() {
        _clientCtxList.Add(OperationContext.Current);
    }
    
  • 备注:

    • 这是记事本代码-它可能包含语法错误,并且可能无法编译
    • 不包括异常处理
    • 不包括锁定_clineCtxList,但强烈建议锁定

    您能否将配置代码或配置文件张贴在设置超时的位置?什么是确切的异常以及引发异常的代码?我已经浪费了太多时间试图解决超时问题。我只是想知道如何设置ping的东西。不过还是要谢谢你。@Jonnster对ping的建议是错误的。你会创造出一个骇人听闻的解决方案,从根本上打击你。@oleksii:我不认为这是完全错误的。ping的一个好处是,在tcp堆栈通知您之前,您就可以捕获孤立的连接。我已使用app.config设置更新了原始帖子,因为我更愿意深入了解这一点。此解决方案可以工作,但是,请考虑以下几点:<代码> ping <代码>没有任何商业价值,但在契约中占用空间,它需要额外的代码,因此bug的概率增加,它对代码增加了绝对不必要的复杂性,它稍微增加了服务上的负载,它需要文档和进一步的代码维护。所有这些都可以通过初始正确的绑定配置来修复。这就是为什么我建议修复根本问题,而不是使用黑客。是的,也许。但op明确要求ping-solution@oleksii-我完全同意你的看法,但事实是WCF太差劲了。这真是垃圾。带回COM、COM+和DCOM的时代。生活变得轻松多了,而且这些东西真的起作用了!在我看来,WCF在中国简直是垃圾。当然,我很想找到解决方案,但谷歌认为这是一个普遍存在的问题,有些人甚至认为这是一个微软不会修复的已知错误。谢谢简。这正是我所想的,可以说,很高兴有人支持这个想法。我不愿意编写代码,因为我同意这感觉有点像是在回避这个问题。它不是垃圾,而是相当复杂,因为该体系结构在每个已知和未知的方向上都是非常可扩展和可配置的。有时很难找到合适的属性来改变你的行为以满足你的需要。也许你应该给我们更多关于绑定和你使用的超时值的信息。
    [OperationContract]
    void Ping();
    
    List<OperationContext> _clientCtxList = new List<OperationContext>();
    
    void IMyService.InitSession() {
        _clientCtxList.Add(OperationContext.Current);
    }
    
    void tmrPing (object state) {
        foreach (var ctx in _clientCtxList)
        {
            // todo: catch exceptions and remove client context 
            //       from list in case of failure
            ctx.GetCallbackChannel<IMyCallbackContract>().Ping();
        }
    
        // restart timer
        _timer.Change(10000, Timeout.Infinite);
    }
    
    System.Threading.Timer _timer;
    
    void Startup() {
        // call my function in 10 seconds
        _timer = new System.Threading.Timer(
                        tmrPing, null, 10000, Timeout.Infinte);
    }