WCF双向调用:意外递归

Posted

技术标签:

【中文标题】WCF双向调用:意外递归【英文标题】:WCF two-way call: unexpected recursion 【发布时间】:2019-01-22 00:00:28 【问题描述】:

我们的 Winforms 模块是一个 WCF 客户端,在处理 WM_PAINT 时它调用 WCF 服务的双向方法。我期待它等待回复;但是会发生递归,导致嵌套的 WM_PAINT,随之而来的是各种问题。 现在我意识到 WM_PAINT 处理程序可能不是通过线路调用的最佳位置,但上述行为首先是如何可能的呢? WCF 客户端线程在等待双向调用的回复时不应该阻塞吗? UI 模块使用了两个第三方库,所以我不确定谁应该为所发生的事情负责。恕我直言,在 WM_PAINT 中通过网络调用不是好的,但它本身不应该引起递归。 这是堆栈:

<Our code – recursion!>
System.dll!System.ComponentModel.TypeConverter.ConvertToString(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
SmartPropertyGrid.dll!VisualHint.SmartPropertyGrid.PropertyValue.ConvertValueToDisplayedString(object value)
SmartPropertyGrid.dll!VisualHint.SmartPropertyGrid.PropertyValueIndirect.HasMultipleTexts(out string text, out bool textIsExceptionText)
SmartPropertyGrid.dll!VisualHint.SmartPropertyGrid.PropertyValue.HasMultipleTexts()
SmartPropertyGrid.dll!VisualHint.SmartPropertyGrid.Property.Draw(System.Drawing.Graphics graphics, System.Drawing.Rectangle itemRect, VisualHint.SmartPropertyGrid.PropertyVisibleDeepEnumerator enumSelf)
SmartPropertyGrid.dll!A.c84db8915b8e0ce02a23aa50484601540.OnPaint(System.Windows.Forms.PaintEventArgs e)
System.Windows.Forms.dll!System.Windows.Forms.Control.PaintWithErrorHandling(System.Windows.Forms.PaintEventArgs e, short layer)
System.Windows.Forms.dll!System.Windows.Forms.Control.WmPaint(ref System.Windows.Forms.Message m)
System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m)
SmartPropertyGrid.dll!A.c84db8915b8e0ce02a23aa50484601540.WndProc(ref System.Windows.Forms.Message m)
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m)
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m)
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Callback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam)
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle waitableSafeHandle, long millisecondsTimeout, bool hasThreadAffinity, bool exitContext)
mscorlib.dll!System.Threading.WaitHandle.WaitOne(System.TimeSpan timeout, bool exitContext)
System.ServiceModel.Internals.dll!System.Runtime.TimeoutHelper.WaitOne(System.Threading.WaitHandle waitHandle, System.TimeSpan timeout)
System.ServiceModel.dll!System.ServiceModel.Dispatcher.DuplexChannelBinder.SyncDuplexRequest.WaitForReply(System.TimeSpan timeout)
System.ServiceModel.dll!System.ServiceModel.Dispatcher.DuplexChannelBinder.Request(System.ServiceModel.Channels.Message message, System.TimeSpan timeout)
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannel.Call(string action, bool oneway, System.ServiceModel.Dispatcher.ProxyOperationRuntime operation, object[] ins, object[] outs, System.TimeSpan timeout)
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(System.Runtime.Remoting.Messaging.IMethodCallMessage methodCall, System.ServiceModel.Dispatcher.ProxyOperationRuntime operation)
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannelProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage message)
mscorlib.dll!System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(ref System.Runtime.Remoting.Proxies.MessageData msgData, int type)
[Native to Managed Transition]
[Managed to Native Transition]
[Managed to Native Transition]  
<Our code>

【问题讨论】:

您在 Paint Message 中调用 WCF 服务?天哪,为什么 无论如何,这至少可以说很奇怪,这里没有足够的信息来帮助你。您将需要进行一些取证调试并找出您正在做的事情的真实性质 @TheGeneral:这是一个遗留代码,我将对其进行改进/重构。 【参考方案1】:

如果您使用代码更新问题,我们可以尝试帮助解决问题。

WM_PAINT 消息的处理应该是超快的。除了与绘画相关的directyl之外的任何其他计算都应该在其他地方(在另一个线程中)完成。重要的是 - 当控件/表单未显示在屏幕上时,可以接收 WM_PAINT 事件。其他东西可以称之为获取控件/表单的“屏幕截图”。

【讨论】:

我相信我们都同意在 WM_PAINT 中做任何“重”的事情都是不好的,句号。真正的难题是为什么会发生递归,而双向调用应该阻塞线程。 @alexk 没有源代码几乎不可能说任何更有用的东西。

以上是关于WCF双向调用:意外递归的主要内容,如果未能解决你的问题,请参考以下文章

JPA在Kotlin和Glassfish中以双向关系无限递归

为啥我的递归会产生意外错误?以及如何在到达循环时修改递归?

使用稍微复杂的方法引用 WCF 服务时获取“递归集合数据契约”

C# 递归方法的意外结果

通过递归方式反向双向链表不在python中迭代

高级双向杰克逊序列化以避免无限递归