c# - IOException on streamed file upload via WCF over HTTP -


i'm building wcf service hosted allows client upload files on http. service reads client's stream chunk chunk. works small file, single iteration needed. when uploading larger files after chunks ioexception saying an exception has been thrown when reading stream. on stream.endread().

the inner exception the i/o operation has been aborted because of either thread exit or application request.

the amount of read chunks varies can't figure out, causes difference. time works varies 300ms 550 ms , ~1mb ~2mb processed.

does have clue?

the interface defined this:

[servicecontract]   public interface iservicefileserver   {     [operationcontract]     uploadresponse uploadfile(uploadrequest uploadrequest);      // status feedback related code left out simplicity     // [operationcontract]     // runningtaskstatus getprogress(guid taskid);    }    [messagecontract]   public class uploadrequest   {     [messageheader()]     public string filename { get; set; }      [messageheader()]     public long sizeinbyte { get; set; }      [messagebodymember(order = 1)]     public stream stream { get; set; }   }    [messagecontract]   public class uploadresponse   {     [messagebodymember()]     public guid taskid { get; set; }   } 

here service implementation:

const int buffersize = 4 * 1024; // called client side public uploadresponse uploadfile(uploadrequest uploadrequest) {   guid taskid = guid.newguid();   stream stream = null;   try   {     stream = uploadrequest.stream;     string filename = uploadrequest.filename;     long sizeinbytes = uploadrequest.sizeinbyte;     byte[] buffer = new byte[buffersize];      stream.beginread(buffer, 0, buffersize, readasynccallback, new asynchelper(buffer, stream, sizeinbytes));   }   catch (exception ex)   {     if (stream != null)       stream.close();   }   return new uploadresponse() { taskid = taskid }; }  // helper class async reading public class asynchelper {   public byte[] bytearray { get; set; }   public stream sourcestream { get; set; }   public long totalsizeinbytes { get; set; }   public long bytesread { get; set; }    public asynchelper(byte[] array, stream sourcestream, long totalsizeinbytes)   {     this.bytearray = array;     this.sourcestream = sourcestream;     this.totalsizeinbytes = totalsizeinbytes;     this.bytesread = 0;   } }  // internal reading of chunk stream private void readasynccallback(iasyncresult ar) {   asynchelper info = ar.asyncstate asynchelper;   int amountread = 0;   try   {     amountread = info.sourcestream.endread(ar);   }   catch (ioexception ex)   {     trace.writeline(ex.message);     info.sourcestream.close();     return;   }    // stream   info.bytesread += amountread;   trace.writeline("info.bytesread: " + info.bytesread);    if (info.sourcestream.position < info.totalsizeinbytes)   {     try     { // read next chunk stream       info.sourcestream.beginread(info.bytearray, 0, info.bytearray.length, readasynccallback, info);     }     catch (ioexception ex)     {       info.sourcestream.close();     }   }   else   {     info.sourcestream.close();        } } 

the binding defined this:

basichttpbinding binding = new basichttpbinding(); binding.transfermode = transfermode.streamed; binding.messageencoding = wsmessageencoding.mtom; binding.maxreceivedmessagesize = 3 * 1024 * 1024; binding.maxbuffersize = 64 * 1024; binding.closetimeout = new timespan(0, 1, 0); binding.opentimeout = new timespan(0, 1, 0); binding.receivetimeout = new timespan(0, 10, 0); binding.sendtimeout = new timespan(0, 1, 0); binding.security.mode = basichttpsecuritymode.none; binding.security.transport.clientcredentialtype = httpclientcredentialtype.none; 

uploadrequest.stream stream provided wcf. stream feeds off underlying tcp connection wcf maintains client of service.

this stream not same object instance service client has passed in. impossible because client , server connected on tcp. not share same address space cannot share object instances.

you returning uploadfile before stream has been processed. wcf cannot know background thread of yours still using stream object. wcf releases resources underlying stream (probably closes tcp connection client).

wcf close stream once request handling method has returned. async processing non-deterministically fail. threading race between using stream , wcf racing close it.

the comments under question show there misunderstanding somewhere i'm not sure is. if need further clarification please leave comment , disagree , why.


Comments