title: IClientChannel antipattern
body: <p>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:</p>
  
  <p>1) ChannelFactory.CreateChannel does not return IClientChannel as an out parameter?</p>
  
  <p>2) .Net documentation for CreateChannel does not mention it?</p>
  
  <p>3) .Net documentation does not show a proper usage pattern in examples (no dispose code)?</p>
  
  <p>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?</p>
  
  <p>Here is an ASP.NET log if someone is interested. </p>
  
  <pre><code>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)
  </code></pre>