/// <summary>
        /// Runs calculation asynchronously.
        /// </summary>
        public async Task RunCalculationAsync()
        {
            var extractBlockOptions = new DataflowBlockOptions
            {
                BoundedCapacity = 1
            };

            var calculationBlockOptions = new ExecutionDataflowBlockOptions()
            {
                BoundedCapacity        = Environment.ProcessorCount * MaxBufferSize * 100,
                MaxDegreeOfParallelism = Environment.ProcessorCount * 100
            };

            var aggregationBlockOptions = new ExecutionDataflowBlockOptions()
            {
                BoundedCapacity        = Environment.ProcessorCount * MaxBufferSize * 2000,
                MaxDegreeOfParallelism = 1
            };

            var linkOptions = new DataflowLinkOptions
            {
                PropagateCompletion = true
            };

            var getBlocks = new BufferBlock <string>(extractBlockOptions);

            var calculateFrequencies = new TransformBlock <string, IDictionary <string, long> >(
                (text) =>
            {
                return(frequencyCalculator.CalculateFrequencies(text));
            },
                calculationBlockOptions);

            var aggregateResult = new ActionBlock <IDictionary <string, long> >(
                (dictionary) =>
            {
                dataAggregator.MergeData(dictionary);
            },
                aggregationBlockOptions);

            getBlocks.LinkTo(calculateFrequencies, linkOptions);
            calculateFrequencies.LinkTo(aggregateResult, linkOptions);

            string buffer = dataReader.GetBlock();

            while (buffer != null)
            {
                await getBlocks.SendAsync(buffer);

                buffer = dataReader.GetBlock();
            }
            getBlocks.Complete();

            await Task.WhenAll(calculateFrequencies.Completion, aggregateResult.Completion);

            dataWriter.SaveDictionary(dataAggregator.GetData());
        }
        public void RunCalculation()
        {
            string buffer = dataReader.GetBlock();

            while (buffer != null)
            {
                dataAggregator.MergeData(
                    frequencyCalculator.CalculateFrequencies(buffer));

                buffer = dataReader.GetBlock();
            }

            dataWriter.SaveDictionary(dataAggregator.GetData());
        }
        /// <summary>
        /// Runs calculation.
        /// </summary>
        public async Task RunCalculationAsync()
        {
            IDictionary <string, long> resultDictionary = new ConcurrentDictionary <string, long>();

            var extractBlockOptions = new DataflowBlockOptions
            {
                BoundedCapacity = 1
            };

            var calculationBlockOptions = new ExecutionDataflowBlockOptions()
            {
                BoundedCapacity        = Environment.ProcessorCount * MaxBufferSize * 100,
                MaxDegreeOfParallelism = Environment.ProcessorCount * 100
            };

            var linkOptions = new DataflowLinkOptions
            {
                PropagateCompletion = true
            };

            var getBlocks = new BufferBlock <string>(extractBlockOptions);

            var calculateFrequencies = new ActionBlock <string>(
                (text) =>
            {
                frequencyCalculator.CalculateFrequencies(text, resultDictionary);
            },
                calculationBlockOptions);

            getBlocks.LinkTo(calculateFrequencies, linkOptions);

            string buffer = dataReader.GetBlock();

            while (buffer != null)
            {
                await getBlocks.SendAsync(buffer);

                buffer = dataReader.GetBlock();
            }
            getBlocks.Complete();

            await Task.WhenAll(calculateFrequencies.Completion);

            dataWriter.SaveDictionary(new SortedDictionary <string, long>(resultDictionary));
        }