Hi Peter (and others)
I eventually wrote my own poor man's BitTorrent to allow upload of large files from the SL4 client to the WCF service. It turned out to be quite straightforward and reasonably neat to code. In a nutshell it goes like this: Server Side int ReceiveChunk(TransferChunk chunk) The chunk contains the transfer Guid id, filename, offset, length and total bytes. So if the client sends a 8MB file in 256KB chunks then it makes 32 calls with the same id and filename, changing the offset and length. The service has a Dictionary<Guid, Torrent> to track the arrival of pieces and when the total bytes have arrived in the full size receiving buffer it saves the file and removes it from the dictionary. I put a timestamp on each entry to know if it's gone stale and can be removed. Client Side It turns out the tricky bit was getting the client to send the chunks on the right thread with a delay between each send. I knew that the client should not send a flood of asynchronous calls for fear of a bottleneck or crash, so I wanted a 0.5 second delay between each send. The delay was a guess and a bit of a hack, but it works nicely. The SL control gets a file from an OpenFileDialog and passes the selected FileInfo, name and length to the controller. I've pasted below the skeleton of the controller method so you can see how I read the file on a worker thread and send the chunks with delays on the UI thread. I've stripped out UI callbacks and other marshalling clutter. Cheers, Greg public void UploadFile(Dispatcher dispatcher, FileInfo file, string name, long length) { ThreadPool.QueueUserWorkItem((o) => { Guid key = Guid.NewGuid(); using (Stream s = file.OpenRead()) { using (BinaryReader br = new BinaryReader(s)) { for (int offset = 0; ; offset += chunkLength) { TransferChunk chunk = new TransferChunk(); chunk.Key = key; chunk.TotalBytes = length; byte[] buffer = new byte[chunkLength]; int readCount = br.Read(buffer, 0, chunkLength); if (readCount == 0) { break; } chunk.Offset = offset; chunk.Length = readCount; chunk.Buffer = buffer; chunk.Filename = name; dispatcher.BeginInvoke(() => { wcfproxy.SendChunk(chunk, (c, e, r) => { /* ignore */ }); }); Thread.Sleep(500); } } } }, marshalled parameters); }