【发布时间】: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 的这种默认行为?
【问题讨论】:
-
我认为你是对的,WaitOne 是问题所在。见stackoverflow.com/questions/896233/…
标签: winforms wcf message-queue