简体   繁体   English

WCF双工nettcp回调不起作用

[英]WCF Duplex nettcp callbacks not working

Environment 环境

There is WCF Service (NET:TCP | Reliable | SecurityEnabled) running as console on Physical Machine A 在物理机A上有作为控制台运行的WCF服务(NET:TCP | Reliable | SecurityEnabled)

There are 20-30 .NET client applications (Winforms) exposed over Citrix so hosted again on One physical machine different from server. 通过Citrix公开了20-30个.NET客户端应用程序(Winforms),因此再次托管在与服务器不同的一台物理计算机上。

Problem 问题

The application structure follows the same pattern as discussed in http://msdn.microsoft.com/en-us/magazine/cc163537.aspx by Juval Lowy. 应用程序结构遵循Juval Lowy在http://msdn.microsoft.com/zh-cn/magazine/cc163537.aspx中讨论的相同模式。

The problem is at the server it is able to invoke the callback with no errors, but the client never receives it. 问题出在服务器上,它能够无任何错误地调用回调,但是客户端永远不会收到它。 There is code tries to subscribe again if no callback call within 60secs. 如果在60秒内没有回调,则有代码尝试再次订阅。 It has a side effect that it opens a new connection by calling Subscribe API on the server. 副作用是,它通过调用服务器上的Subscribe API来打开新连接。 Over a period you can see many TCP connections open on the server. 在一段时间内,您可以看到服务器上打开了许多TCP连接。 No errors but still client callback is never invoked. 没有错误,但永远不会调用客户端回调。

Additional Information 附加信息

Sometimes following error is thrown: 有时会引发以下错误:

The message could not be transferred within the allotted timeout of 00:01:00. 无法在指定的超时时间00:01:00内传输该消息。 There was no space available in the reliable channel's transfer window. 可靠通道的传输窗口中没有可用空间。 The time allotted to this operation may have been a portion of a longer timeout. 分配给该操作的时间可能是较长超时的一部分。

In addition MaxBufferPoolSize is set to Int64.MaxValue as you can see in the code below 另外,如下面的代码所示,MaxBufferPoolSize设置为Int64.MaxValue。

var binding = new NetTcpBinding(SecurityMode.Transport, reliableSession);
binding.ReliableSession.Enabled = true;
binding.ReliableSession.InactivityTimeout = TimeSpan.FromDays(1);
binding.ReliableSession.Ordered = true;
binding.CloseTimeout = TimeSpan.FromHours(1);
binding.SendTimeout = TimeSpan.FromHours(1);
binding.ReceiveTimeout = TimeSpan.FromHours(1);
binding.OpenTimeout = TimeSpan.FromHours(1);
binding.ReaderQuotas.MaxDepth = Int32.MaxValue;
binding.ReaderQuotas.MaxStringContentLength = Int32.MaxValue;
binding.ReaderQuotas.MaxArrayLength = Int32.MaxValue;
binding.ReaderQuotas.MaxBytesPerRead = Int32.MaxValue;
binding.ReaderQuotas.MaxNameTableCharCount = Int32.MaxValue;
binding.MaxBufferPoolSize = Int64.MaxValue;
binding.MaxReceivedMessageSize = Int32.MaxValue;

Any suggestions will be great help! 任何建议都会有很大帮助!

Recent findings: 最近的发现:

I recently discovered the callback on the client side has different kinds of processing based on what is visible on the user screen. 我最近发现,基于用户屏幕上可见的内容,客户端上的回调具有不同类型的处理。 This was blocking the callbacks to be acknowledged. 这阻止了回调被确认。 That explains the buffer overflow as well. 那也解释了缓冲区溢出。 The frequency of notifications sent from the server is very high compared to the time taken by each client to process them. 与每个客户端处理通知的时间相比,从服务器发送通知的频率非常高。

Apart from the changes I did like disabling security, configuring timeouts correctly, following line of code helped a lot: 除了我喜欢禁用安全性的更改,正确配置超时外,以下代码行也有很大帮助:

   public void OnNotification(AmigoMessage messsage)
    {
        ThreadPool.QueueUserWorkItem((x) => { ProcessNotification(messsage); });
    }

Take a look at [CallbackBehavior(UseSynchronizationContext = false)] . 看看[CallbackBehavior(UseSynchronizationContext = false)] Not having this attribute on the callback service will try to marshal to (usually) the UI thread. 回调服务上没有此属性将尝试封送(通常)UI线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM