// This is the method that the underlying, free-threaded
        // asynchronous behavior will invoke.  This will happen on
        // an arbitrary thread.
        private void OnAsyncCompletionMethod(object operationState)
        {
            AsyncData      data    = operationState as AsyncData;
            AsyncOperation asyncOp = data.Operation;
            AsyncOperationCompletedEventArgs args = new AsyncOperationCompletedEventArgs(data);

            // In this case, don't allow cancellation, as the method
            // is about to raise the completed event.
            lock (_userStateToLifetime.SyncRoot)
            {
                if (!_userStateToLifetime.Contains(data.UserData))
                {
                    asyncOp = null;
                }
                else
                {
                    _userStateToLifetime.Remove(asyncOp.UserSuppliedState);
                }
            }

            // The asyncOp object is responsible for marshaling
            // the call.
            if (asyncOp != null)
            {
                asyncOp.PostOperationCompleted(_onCompletedDelegate, args);
            }

            // Note that after the call to OperationCompleted,
            // asyncOp is no longer usable, and any attempt to use it
            // will cause an exception to be thrown.
        }
        private MemoryStream CopyResponseToMemory(AsyncData data, Stream responseStream, long contentLength)
        {
            if (responseStream == null)
            {
                return(null);
            }

            // read the stream into memory. That's the only way to satisfy the "main work
            // on the other thread requirement
            MemoryStream memStream = new MemoryStream();
            const int    size      = 4096;
            var          bytes     = new byte[size];

            int    numBytes;
            double current      = 0;
            long   bytesWritten = 0;

            while ((numBytes = responseStream.Read(bytes, 0, size)) > 0)
            {
                memStream.Write(bytes, 0, numBytes);
                if (data == null || data.Delegate == null)
                {
                    continue;
                }

                bytesWritten += numBytes;

                if (contentLength > size)
                {
                    current = bytesWritten * 100d / contentLength;
                }

                // see if we are still in the list...
                // Multiple threads will access the task dictionary,
                // so it must be locked to serialize access.
                if (CheckIfOperationIsCancelled(data.UserData))
                {
                    throw new ArgumentException("Operation was cancelled");
                }

                var args = new AsyncOperationProgressEventArgs(
                    contentLength,
                    bytesWritten,
                    (int)current,
                    data.UriToUse,
                    data.HttpVerb,
                    data.UserData);
                data.Operation.Post(data.Delegate, args);
            }

            memStream.Seek(0, SeekOrigin.Begin);

            return(memStream);
        }
 /// <summary>
 /// handles the response stream
 /// copies it into the memory stream, or parses it into a feed.
 /// </summary>
 /// <param name="data"></param>
 /// <param name="responseStream"></param>
 /// <param name="contentLength"></param>
 /// <returns></returns>
 protected override void HandleResponseStream(AsyncData data, Stream responseStream, long contentLength)
 {
     if (data.ParseFeed)
     {
         data.Feed       = CreateAndParseFeed(responseStream, data.UriToUse);
         data.DataStream = null;
     }
     else
     {
         base.HandleResponseStream(data, responseStream, contentLength);
     }
 }
        /// <summary>
        /// handles the response stream
        /// copies it into the memory stream, or parses it into a feed.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="responseStream"></param>
        /// <param name="contentLength"></param>
        /// <returns></returns>
        protected virtual void HandleResponseStream(AsyncData data, Stream responseStream, long contentLength, IService service)
        {
            data.DataStream = CopyResponseToMemory(data, responseStream, contentLength);

            IAsyncEntryData entryData   = data as IAsyncEntryData;
            Service         serviceImpl = service as Service;

            if (entryData != null && service != null)
            {
                entryData.Entry = serviceImpl.CreateAndParseEntry(data.DataStream, data.UriToUse);
            }
        }
        internal bool SendProgressData(AsyncData data, AsyncOperationProgressEventArgs args)
        {
            // In this case, don't allow cancellation, as the method
            // is about to raise the completed event.
            bool ret = !CheckIfOperationIsCancelled(data.UserData);

            if (ret)
            {
                data.Operation.Post(data.Delegate, args);
            }

            return(ret);
        }
        /// <summary>
        /// constructor. takes the async data blob
        /// </summary>
        /// <param name="data">async data to constructor</param>
        internal AsyncOperationCompletedEventArgs(AsyncData data)
            : base(data.Exception, false, data.UserData)
        {
            _feedObject = data.Feed;
            _stream     = data.DataStream;

            IAsyncEntryData entryData = data as IAsyncEntryData;

            if (entryData != null)
            {
                _entryObject = entryData.Entry;
            }
        }
        /// <summary>
        /// this method cancels the corresponding async operation.
        /// It sends still a completed event, but that event will then
        /// have the cancel property set to true
        /// </summary>
        /// <param name="userData">your identifier for the operation to be cancelled</param>
        public void CancelAsync(object userData)
        {
            lock (_userStateToLifetime.SyncRoot)
            {
                object obj = _userStateToLifetime[userData];
                if (obj != null)
                {
                    _userStateToLifetime.Remove(userData);

                    AsyncOperation asyncOp = obj as AsyncOperation;
                    // The asyncOp object is responsible for
                    // marshaling the call to the proper
                    // thread or context.

                    AsyncData data = new AsyncData(null, userData, _onProgressReportDelegate);
                    AsyncOperationCompletedEventArgs args = new AsyncOperationCompletedEventArgs(data, true);

                    asyncOp.PostOperationCompleted(_onCompletedDelegate, args);
                }
            }
        }
 internal AsyncOperationCompletedEventArgs(AsyncData data, bool cancelled)
     : base(data.Exception, cancelled, data.UserData)
 {
 }
 /// <summary>
 /// handles the response stream
 /// copies it into the memory stream, or parses it into a feed.
 /// </summary>
 /// <param name="data"></param>
 /// <param name="responseStream"></param>
 /// <param name="contentLength"></param>
 /// <returns></returns>
 protected virtual void HandleResponseStream(AsyncData data, Stream responseStream, long contentLength)
 {
     HandleResponseStream(data, responseStream, contentLength, null);
 }