.net - Premature disposing a MessageBodyStream in WCF -


i using wcf download long file. self hosted service on net-tcp binding. on client reading stream , writing disk in background thread. on ui, there cancel button. cancel read-write loop using cancellationtoken.

problem is,

if stream premature (not eof) takes long dispose it.

at server (c#):

io.stream getfile(string filepath) {     return new io.filestream(filepath); } 

at client (vb):

using proxy new servicereference1.testserver     using wcfstrm = proxy.getfile("c:\100mb.dat")         using filestrm = new filestream("d:\destination\100mb.dat")              dim buff(256) new byte              while true                 cancellationtoken.throwifcancellationrequested                  dim len = wcfstrm.read(buff, 0, buff.length)                  if len > 0                     filestrm.write(buff, 0, len)                 else                     exit while                 end if              end while           end using           end using ' <-------------- hangs 10mins end using 

when cancellationtoken throws operationcancelledexception, 3 using blocks try dispose resources. when second using block tries dispose messagebodystream, hangs 10 minutes. if stream read, exits quickly.

i suspected, had receivetimeout of 10 mins. changed 30 seconds , viola! dispose takes 30 seconds.

one more thing. dispose operation timeouts. eats operationcancelledexception , produces timeoutexception saying the sockket transfer timed out after 00:00:00... bla bla bla

following stack trace

system.timeoutexception: socket transfer timed out after 00:00:00. have exceeded timeout set on binding. time allotted operation may have been portion of longer timeout.    @ system.servicemodel.channels.socketconnection.setreadtimeout(timespan timeout, boolean synchronous, boolean closing)    @ system.servicemodel.channels.socketconnection.readcore(byte[] buffer, int32 offset, int32 size, timespan timeout, boolean closing)    @ system.servicemodel.channels.socketconnection.read(byte[] buffer, int32 offset, int32 size, timespan timeout)    @ system.servicemodel.channels.delegatingconnection.read(byte[] buffer, int32 offset, int32 size, timespan timeout)    @ system.servicemodel.channels.prereadconnection.read(byte[] buffer, int32 offset, int32 size, timespan timeout)    @ system.servicemodel.channels.singletonconnectionreader.singletoninputconnectionstream.readcore(byte[] buffer, int32 offset, int32 count)    @ system.servicemodel.channels.singletonconnectionreader.singletoninputconnectionstream.read(byte[] buffer, int32 offset, int32 count)    @ system.servicemodel.channels.maxmessagesizestream.read(byte[] buffer, int32 offset, int32 count)    @ system.servicemodel.channels.singletonconnectionreader.close(timespan timeout)    @ system.servicemodel.channels.singletonconnectionreader.singletoninputconnectionstream.close()    @ system.servicemodel.channels.delegatingstream.close()    @ system.xml.xmlbufferreader.close()    @ system.xml.xmlbasereader.close()    @ system.xml.xmlbinaryreader.close()    @ system.servicemodel.dispatcher.streamformatter.messagebodystream.close()    @ system.io.stream.dispose()    @ ...somewhere in code... 

i not convinced once cannot cancel stream without reading it. on other hand cannot forget stream , let go without disposing. has blocking wait-until-safely-released call.

can please me out here?

edit

the stack trace shows:

'                                                         interesting    @ system.xml.xmlbinaryreader.close() '                    vvvvvvvvvvvvv    @ system.servicemodel.dispatcher.streamformatter.messagebodystream.close()    @ system.io.stream.dispose() 

so changed using block try-finally block. there put wcfstrm.close followed wcfstrm.dispose. astonishment, close statement passed swiftly , dispose timed out. if inside dispose actual culprit close why did explicit close didnt hang? , again dispose hanged when stream closed?

to clarify, implementation of stream.dispose() call stream.close(). base implementation of stream.close() call stream.dispose(bool). it's counter guidelines of how typically implement idisposable, it's worth noting.

the messagebodystream.close() method implemented first close message being read, close xmldictionaryreader associated stream.

looking @ full stack trace, problem seems reader calls singletonconnectionreader.close(timespan). takes timespan timeout, , source of timeoutexception replacing operationcancelledexception.

this method attempts read rest of stream complete close operation. can't explain rationale behind that, how is.


to fix problem, must stop using proxy class are. despite being idisposable, it's not safe use wcf proxy in using block, because calling dispose() calls close(), , in event of exception, that's not mean.

in case, calling abort() on proxy fix problem completely, because it's mean: abort operation.

using proxy new servicereference1.testserver     dim wcfstrm = proxy.getfile("c:\100mb.dat")      try         using filestrm = new filestream("d:\destination\100mb.dat")              dim buff(256) new byte              while true                 cancellationtoken.throwifcancellationrequested                  dim len = wcfstrm.read(buff, 0, buff.length)                  if len > 0                     filestrm.write(buff, 0, len)                 else                     exit while                 end if              end while           end using           end try     catch         proxy.abort()     end catch             wcfstrm.dispose()     end end using 

i'm not vb developer, apologise if syntax terrible.


Comments

Popular posts from this blog

c++ - CryptStringToBinary API behavior -

java.util.scanner - How to read and add only numbers to array from a text file -

iphone - Three second countdown in cocos2d -