/// <summary>
        /// Start producing results for given context.
        /// Provided consumer is notified whenever progress is made
        /// (new value is ready or error occurs).
        /// </summary>
        public void ProduceResults(
            IConsumer <EncodedImage> consumer,
            IProducerContext producerContext)
        {
            IProducerListener listener     = producerContext.Listener;
            string            requestId    = producerContext.Id;
            ImageRequest      imageRequest = producerContext.ImageRequest;
            StatefulProducerRunnable <EncodedImage> cancellableProducerRunnable =
                new StatefulProducerRunnableImpl <EncodedImage>(
                    consumer,
                    listener,
                    ProducerName,
                    requestId,
                    null,
                    null,
                    null,
                    null,
                    null,
                    null,
                    (result) =>
            {
                EncodedImage.CloseSafely(result);
            },
                    async() =>
            {
                EncodedImage encodedImage = await GetEncodedImage(imageRequest)
                                            .ConfigureAwait(false);

                if (encodedImage == null)
                {
                    return(null);
                }

                await encodedImage.ParseMetaDataAsync().ConfigureAwait(false);
                return(encodedImage);
            });

            producerContext.AddCallbacks(
                new BaseProducerContextCallbacks(
                    () =>
            {
                cancellableProducerRunnable.Cancel();
            },
                    () => { },
                    () => { },
                    () => { }));

            _executor.Execute(cancellableProducerRunnable.Runnable);
        }
        /// <summary>
        /// Start producing results for given context.
        /// Provided consumer is notified whenever progress is made
        /// (new value is ready or error occurs).
        /// </summary>

        public void ProduceResults(IConsumer <T> consumer, IProducerContext context)
        {
            IProducerListener            producerListener = context.Listener;
            string                       requestId        = context.Id;
            StatefulProducerRunnable <T> statefulRunnable = new StatefulProducerRunnableImpl <T>(
                consumer,
                producerListener,
                PRODUCER_NAME,
                requestId,
                (T ignored) =>
            {
                producerListener.OnProducerFinishWithSuccess(requestId, PRODUCER_NAME, null);
                _inputProducer.ProduceResults(consumer, context);
            },
                null,
                null,
                (_) =>
            {
                return(default(IDictionary <string, string>));
            },
                (_) =>
            {
                return(default(IDictionary <string, string>));
            },
                () =>
            {
                return(default(IDictionary <string, string>));
            },
                null,
                () =>
            {
                return(Task.FromResult(default(T)));
            });

            context.AddCallbacks(
                new BaseProducerContextCallbacks(
                    () =>
            {
                statefulRunnable.Cancel();
                _threadHandoffProducerQueue.Remove(statefulRunnable.Runnable);
            },
                    () => { },
                    () => { },
                    () => { }));

            _threadHandoffProducerQueue.AddToQueueOrExecute(statefulRunnable.Runnable);
        }
        /// <summary>
        /// Start producing results for given context.
        /// Provided consumer is notified whenever progress is made
        /// (new value is ready or error occurs).
        /// </summary>
        public void ProduceResults(
            IConsumer <EncodedImage> consumer,
            IProducerContext producerContext)
        {
            IProducerListener listener     = producerContext.Listener;
            string            requestId    = producerContext.Id;
            ImageRequest      imageRequest = producerContext.ImageRequest;

            StatefulProducerRunnable <EncodedImage> cancellableProducerRunnable =
                new StatefulProducerRunnableImpl <EncodedImage>(
                    consumer,
                    listener,
                    PRODUCER_NAME,
                    requestId,
                    null,
                    null,
                    null,
                    (result) =>
            {
                IDictionary <string, string> extraMap = new Dictionary <string, string>()
                {
                    { CREATED_THUMBNAIL, (result != null).ToString() }
                };

                return(new ReadOnlyDictionary <string, string>(extraMap));
            },
                    null,
                    null,
                    (result) =>
            {
                EncodedImage.CloseSafely(result);
            },
                    async() =>
            {
                Uri sourceUri    = imageRequest.SourceUri;
                StorageFile file = await StorageFile
                                   .GetFileFromApplicationUriAsync(sourceUri)
                                   .AsTask()
                                   .ConfigureAwait(false);

                using (var fileStream = await file.OpenReadAsync().AsTask().ConfigureAwait(false))
                {
                    byte[] bytes = await BitmapUtil
                                   .GetThumbnailAsync(fileStream)
                                   .ConfigureAwait(false);

                    if (bytes != null)
                    {
                        IPooledByteBuffer pooledByteBuffer =
                            _pooledByteBufferFactory.NewByteBuffer(bytes);

                        return(await BuildEncodedImage(pooledByteBuffer, fileStream)
                               .ConfigureAwait(false));
                    }
                    else
                    {
                        return(null);
                    }
                }
            });

            producerContext.AddCallbacks(
                new BaseProducerContextCallbacks(
                    () =>
            {
                cancellableProducerRunnable.Cancel();
            },
                    () => { },
                    () => { },
                    () => { }));

            _executor.Execute(cancellableProducerRunnable.Runnable);
        }