/// <summary>
 /// 
 /// </summary>
 /// <param name="progress"></param>
 private void OnUploadProgress(UploadProgressArgs progress)
 {
     if (this.UploadProgress != null)
     {
         this.UploadProgress(this, progress);
     }
 }
        /// <summary>
        /// Initiates async upload of blob data from a stream.
        /// </summary>
        /// <param name="stream">Stream containing data to be uploaded.</param>
        /// <param name="state">State to be passed as userState in the progress and completion event args.</param>
        public void UploadAsync(Stream stream, object state)
        {
            ThreadPool.QueueUserWorkItem(
                new WaitCallback((object o) =>
                {
                    UploadCompletedArgs e = new UploadCompletedArgs(null, false, o);
                    UploadProgressArgs progress = new UploadProgressArgs(o);
                    SmashClient client = new SmashClient(this.identity);
                    try
                    {
                        using (var streamcopy = stream)
                        {
                            stream = null;
                            streamcopy.Position = 0;

                            int id = 0;
                            long length = streamcopy.Length;
                            int multiplier = 1;
                            for (long len = 0; len < length && !progress.Cancel; )
                            {
                                byte[] data = new byte[65536 * multiplier];
                                int read = streamcopy.Read(data, 0, (int)Math.Min(65536 * multiplier, length - len));
                                if (read == 0)
                                {
                                    throw new System.IO.EndOfStreamException("Stream shorter than expected.");
                                }

                                if (read < data.Length)
                                {
                                    byte[] tmp = new byte[read];
                                    Array.Copy(data, tmp, read);
                                    data = tmp;
                                }

                                long duration = DateTime.UtcNow.Ticks;
                                client.AddPageToBlob(this.meetingToken, this.sessionID, this.clientID, this.blobAddress, this.blobSharedSignature, data, id, len + read >= length);
                                duration = ((DateTime.UtcNow.Ticks - duration) / 10000) + 1;

                                multiplier = Math.Max(1, Math.Min(16, 10000 / (int)duration));

                                len += read;
                                id++;

                                progress.UploadedSize = len;
                                OnUploadProgress(progress);
                            }
                        }

                        if (progress.Cancel)
                        {
                            e = new UploadCompletedArgs(null, true, o);
                        }
                        else
                        {
                            e.BlobAddress = this.blobAddress;
                        }
                    }
                    catch (Exception ex)
                    {
                        e = new UploadCompletedArgs(ex, false, o);
                    }
                    finally
                    {
                        client.Dispose();
                    }

                    OnUploadCompleted(e);
                }),
            state);
        }