我刚刚花了 4 个小时(在英国是凌晨 3 点)尝试调试 ASP.NET 应用程序,该应用程序导致框架管理的线程(即不是我的线程)出现异常。我刚刚发现静态方法 ChannelFactory.CreateChannel 的结果可以转换为 IClientChannel 并显式处置。我的意思是这一切都很好,但为什么:
1) ChannelFactory.CreateChannel 不返回 IClientChannel 作为输出参数?
2) CreateChannel 的 .Net 文档没有提到它?
3) .Net 文档在示例中没有显示正确的使用模式(没有处理代码)?
不要误会我的意思——我喜欢 .Net 框架。 Microsoft(和 Krzysztof Cwalina:请参阅设计框架指南)做得非常出色。这就是为什么我没想到会有这样的灾难。我的意思是我到底应该怎么知道我的 IMyService 变量也支持 IClientChannel 并且我应该明确地处理它?</p>
如果有人感兴趣,这里有一个 ASP.NET 日志。
Event Type: Error
Event Source: ASP.NET 2.0.50727.0
Event Category: None
Event ID: 1334
Date: 12/08/2009
Time: 01:55:47
User: N/A
Computer: WLGH3GIS
Description:
An unhandled exception occurred and the process was terminated.
Application ID: /LM/W3SVC/1/Root/Maps
Process ID: 3044
Exception: System.NullReferenceException
Message: Object reference not set to an instance of an object.
StackTrace: at System.Threading.Overlapped.Free(NativeOverlapped* nativeOverlappedPtr)
at System.ServiceModel.Channels.OverlappedContext.Free()
at System.ServiceModel.Channels.PipeConnection.CloseHandle(Boolean abort, String timeoutErrorString, TransferOperation transferOperation)
at System.ServiceModel.Channels.PipeConnection.Close(TimeSpan timeout)
at System.ServiceModel.Channels.BufferedConnection.Close(TimeSpan timeout)
at System.ServiceModel.Channels.ConnectionPool.CloseItem(IConnection item, TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationPool`2.EndpointConnectionPool.CloseItem(TItem item, TimeSpan timeout)
at System.ServiceModel.Channels.IdlingCommunicationPool`2.IdleTimeoutEndpointConnectionPool.CloseItem(TItem item, TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationPool`2.EndpointConnectionPool.CloseIdleConnection(TItem connection, TimeSpan timeout)
at System.ServiceModel.Channels.IdlingCommunicationPool`2.IdleTimeoutEndpointConnectionPool.IdleTimeoutIdleConnectionPool.OnIdle()
at System.ServiceModel.Channels.IdlingCommunicationPool`2.IdleTimeoutEndpointConnectionPool.IdleTimeoutIdleConnectionPool.OnIdle(Object state)
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke2()
at System.Security.SecurityContext.Run(SecurityContext securityContext, ContextCallback callback, Object state)
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke()
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ProcessCallbacks()
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.CompletionCallback(Object state)
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
最佳答案
Karol,我知道这有点老了,但我想说声谢谢。你的帖子真的帮了我大忙。
我遇到的症状是,当我尝试关闭服务器上的 ChannelFactory 时,它总是会超时,无论我为 OpenTimeout、ReceiveTimeout、SendTimeout、InactivityTimeout 或 CloseTimeout 设置的时间跨度如何。
解决方案实际上是在客户端,将 ChannelFactory.CreateChannel 返回的 IMyServiceInterface 转换为 ICommunicationObject。然后,它可以很好地传递给 Util.SafeCloseAndDispose(ICommunicationObject) 方法,您会看到它在整个网络上被复制和粘贴。
在我的客户端上完成之后,服务器的 ChannelFactory 可以在一两秒内关闭,不再超时。
据我所知,Karol 的帖子中的这一见解是网上唯一阐明此问题的地方之一。
再次感谢卡罗尔! :)
关于c# - IClientChannel 反模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1263916/