I use WCF to upload a very long file. This is a self-service net-tcp binding service. On the client, I read the stream and write it to disk in the background stream. There is a cancel button in the user interface. I am canceling the read / write cycle using the CancellationToken .
The problem is,
if the thread is premature (not EOF), then it must be disposed of for too long.
on server (C #):
IO.Stream getFile(string filePath) { return new IO.FileStream(filePath); }
on the client (vb):
using proxy as new ServiceReference1.TestServer using wcfStrm = proxy.getFile("c:\100MB.dat") using fileStrm = new FileStream("d:\destination\100MB.dat") dim buff(256) as new Byte while true cancellationToken.ThrowIfCancellationRequested Dim len = wcfStrm.Read(buff, 0, buff.Length) if len > 0 then fileStrm.write(buff, 0, len) else exit while end if end while end using end using ' <-------------- this hangs for 10Mins end using
When a CancellationToken throws an OperationCancelledException , all three usage blocks try to destroy their resources. Now, when the second block in use tries to recycle MessageBodyStream , it freezes for 10 minutes. but if the stream is fully read, it quickly terminates.
I suspected that it had something to do with ReceiveTimeout 10 minutes. so I changed it to 30 seconds and alt! Disposal now takes 30 seconds.
One more thing. The Dispose operation actually disables. He eats my OperationCancelledException and throws a TimeoutException message The sockket transfer timed out after 00:00:00... bla bla bla
next is a stack trace
System.TimeoutException: The socket transfer timed out after 00:00:00. You have exceeded the timeout set on your binding. The time allotted to this operation may have been a portion of a longer timeout. at System.ServiceModel.Channels.SocketConnection.SetReadTimeout(TimeSpan timeout, Boolean synchronous, Boolean closing) at System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, Boolean closing) at System.ServiceModel.Channels.SocketConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout) at System.ServiceModel.Channels.DelegatingConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout) at System.ServiceModel.Channels.PreReadConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout) at System.ServiceModel.Channels.SingletonConnectionReader.SingletonInputConnectionStream.ReadCore(Byte[] buffer, Int32 offset, Int32 count) at System.ServiceModel.Channels.SingletonConnectionReader.SingletonInputConnectionStream.Read(Byte[] buffer, Int32 offset, Int32 count) at System.ServiceModel.Channels.MaxMessageSizeStream.Read(Byte[] buffer, Int32 offset, Int32 count) at System.ServiceModel.Channels.SingletonConnectionReader.Close(TimeSpan timeout) at System.ServiceModel.Channels.SingletonConnectionReader.SingletonInputConnectionStream.Close() at System.ServiceModel.Channels.DelegatingStream.Close() at System.Xml.XmlBufferReader.Close() at System.Xml.XmlBaseReader.Close() at System.Xml.XmlBinaryReader.Close() at System.ServiceModel.Dispatcher.StreamFormatter.MessageBodyStream.Close() at System.IO.Stream.Dispose() at ...somewhere in my code...
I am not sure that once I can not cancel the stream without reading it completely. On the other hand, I canβt just forget the stream and let it go without recycling. It should be a blocking wait until a safe exit.
Can anyone help me here?
Edit
The stack trace shows:
' this is interesting at System.Xml.XmlBinaryReader.Close() ' VVVVVVVVVVVVV at System.ServiceModel.Dispatcher.StreamFormatter.MessageBodyStream.Close() at System.IO.Stream.Dispose()
So, I changed the use block to a try-finally block. there I put wcfStrm.close and then wcfStrm.Dispose . to my surprise, the close statement passed quickly, and the order was timed. Now, if inside the order the actual culprit was Close , then why didn't the explicit closure hang? and then destroy the hanged again, even when the stream is closed?