【问题标题】:How do I stop WCF from message pumping while it is waiting on a synchronous call?如何在 WCF 等待同步调用时停止消息泵送?
【发布时间】:2011-10-27 18:12:38
【问题描述】:

我有一种情况,比如 wm_paint 等基本消息在它的处理中会触发调用 WCF Webservices,例如,当它需要远程格式化信息时。

但是,当 WCF 等待该调用返回时,消息会不断被抽取,最终可能会在另一条消息中触发相同的调用。

-线程安全对我的问题没有帮助,因为这是“假”多线程 - 它始终是同一个线程解释来自泵的消息。

-重入安全对我没有帮助,因为第二次调用需要远程信息才能正确执行。

查看以下(简化的)调用堆栈:

    MyService.DoSomething(System.String)
    [...]
    Grid.OnPaint(System.Windows.Forms.PaintEventArgs)   System.Windows.Forms.Control.PaintWithErrorHandling(System.Windows.Forms.PaintEventArgs, Int16, Boolean)
    System.Windows.Forms.Control.WmPaint(System.Windows.Forms.Message ByRef)
    System.Windows.Forms.Control.WndProc(System.Windows.Forms.Message ByRef)
    System.Windows.Forms.ContainerControl.WndProc(System.Windows.Forms.Message ByRef)
    System.Windows.Forms.Control+ControlNativeWindow.OnMessage(System.Windows.Forms.Message ByRef)
    System.Windows.Forms.Control+ControlNativeWindow.WndProc(System.Windows.Forms.Message ByRef)
    System.Windows.Forms.NativeWindow.Callback(IntPtr, Int32, IntPtr, IntPtr)
    System.Threading.WaitHandle.WaitOneNative(Microsoft.Win32.SafeHandles.SafeWaitHandle, UInt32, Boolean, Boolean)
    System.Threading.WaitHandle.WaitOne(Int64, Boolean)
    System.Threading.WaitHandle.WaitOne(Int32, Boolean)
    System.Net.LazyAsyncResult.WaitForCompletion(Boolean)
    System.Net.Connection.SubmitRequest(System.Net.HttpWebRequest)
    System.Net.ServicePoint.SubmitRequest(System.Net.HttpWebRequest, System.String)
    System.Net.HttpWebRequest.SubmitRequest(System.Net.ServicePoint)
    System.Net.HttpWebRequest.GetRequestStream(System.Net.TransportContext ByRef)
    System.Net.HttpWebRequest.GetRequestStream()
    System.ServiceModel.Channels.HttpOutput+WebRequestHttpOutput.GetOutputStream()
    System.ServiceModel.Channels.HttpOutput.Send(System.TimeSpan)
    System.ServiceModel.Channels.HttpChannelFactory+HttpRequestChannel+HttpChannelRequest.SendRequest(System.ServiceModel.Channels.Message, System.TimeSpan)
    System.ServiceModel.Channels.RequestChannel.Request(System.ServiceModel.Channels.Message, System.TimeSpan)
    System.ServiceModel.Channels.SecurityChannelFactory1+SecurityRequestChannel[[System.__Canon, mscorlib]].Request(System.ServiceModel.Channels.Message, System.TimeSpan)
    System.ServiceModel.Dispatcher.RequestChannelBinder.Request(System.ServiceModel.Channels.Message, System.TimeSpan)
    System.ServiceModel.Dispatcher.ProxyOperationRuntime, System.Object[], System.Object[], System.TimeSpan)
    System.ServiceModel.Dispatcher.ProxyOperationRuntime, System.Object[], System.Object[])
    System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(System.Runtime.Remoting.Messaging.IMethodCallMessage, System.ServiceModel.Dispatcher.ProxyOperationRuntime)
    System.ServiceModel.Channels.ServiceChannelProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage)
    System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(System.Runtime.Remoting.Proxies.MessageData ByRef, Int32)
    [...]
    MyService.DoSomething(System.String)
    [...]
    System.Windows.Forms.Control.WmMouseUp(System.Windows.Forms.Message ByRef, System.Windows.Forms.MouseButtons, Int32)
    System.Windows.Forms.Control.WndProc(System.Windows.Forms.Message ByRef)
    System.Windows.Forms.Control+ControlNativeWindow.WndProc(System.Windows.Forms.Message ByRef)
    System.Windows.Forms.NativeWindow.Callback(IntPtr, Int32, IntPtr, IntPtr)
System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG ByRef)
System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32, Int32, Int32)
    System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)
    System.Windows.Forms.ApplicationContext)
    System.Windows.Forms.Application.Run(System.Windows.Forms.Form)
    [...]
    MyApplication.Main()

我已经剪切了调用堆栈的顶部,但是您可以通过调用堆栈中出现两次 MyService.DoSomething(System.String) 行来了解它的去向。

我们看到那里的某个地方调用了 System.Threading.WaitHandle.WaitOne(Int64, Boolean)。

我怀疑第二个参数 (exitSynchronisationContext) 传递了“true”,从而允许消息泵继续泵送。

有什么方法可以避免 WCF 的这种默认行为?

【问题讨论】:

标签: winforms wcf message-queue


【解决方案1】:

您正在调用 WCF 调用以响应 WM_PAINT!?这对我来说似乎很可怕。 :/

即使您可以强制停止消息泵,在调用完成时您最终会得到一个无响应的 GUI。如果网络超时或其他原因导致调用需要几秒钟怎么办?

您不能预加载所需的信息吗?或者至少是延迟加载,因此 WCF 调用只被调用一次。这样你还可以在 load 方法中设置一个标志来指示调用是否已经在进行中。

【讨论】:

    猜你喜欢
    • 2010-10-28
    • 2015-04-15
    • 2016-03-29
    • 1970-01-01
    • 2023-03-08
    • 2018-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多