tags:

views:

165

answers:

1

I've just spend 4 hours (it's 3am in the UK) trying to debug ASP.NET application which caused an exception in a thread managed by Framework (i.e. not my thread). I've just found out that a result from the static method ChannelFactory.CreateChannel can be cast to IClientChannel and explicitly Disposed. I mean that's all fine and nice but why:

1) ChannelFactory.CreateChannel does not return IClientChannel as an out parameter?

2) .Net documentation for CreateChannel does not mention it?

3) .Net documentation does not show a proper usage pattern in examples (no dispose code)?

Don't get me wrong - I love .Net framework. Microsoft (and Krzysztof Cwalina: see Designing Framework Guidelines) has done a really great job. That's why I didn't expect a such disaster. I mean how the hell I should know that my IMyService variable also supports IClientChannel and I should explicitly dispose it?

Here is an ASP.NET log if someone is interested.

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)
+1  A: 

Karol, I know this is a bit old, but I wanted to say thank you. Your post really helped me out.

The symptom I had was that when I tried to Close a ChannelFactory on the Server, it would always give a Timeout, regardless of the length of timespan I set for OpenTimeout, ReceiveTimeout, SendTimeout, InactivityTimeout, or CloseTimeout.

The solution was actually on the client, to cast the IMyServiceInterface that was returned by ChannelFactory.CreateChannel to ICommunicationObject. Then, it can be passed nicely to the Util.SafeCloseAndDispose(ICommunicationObject) method that you see copy and pasted all over the web.

After I did that on my client, then the Server's ChannelFactory can be closed in only a second or two, with no more timeout.

As far as I know, this insight from Karol's post is one of the only places online where this problem is spelled out.

Thanks again, Karol! :)

HugeHugh
You are very welcome. I guess it is always good to publish one's findings. You never know when someone else will google it.
Karol Kolenda