Example #1
0
        private int SortBlocksParallel(RecordsReader recordsReader, int field, int workersCount,
                                       out RecordsBuffer firstBlock)
        {
            firstBlock = null;
            IEnumerator <RecordsBuffer> blocks = recordsReader.ReadBlocks().GetEnumerator();

            if (!blocks.MoveNext())
            {
                return(0);
            }

            if (recordsReader.IsLastBlock)
            {
                firstBlock = blocks.Current;
                firstBlock.Sort(field);
                return(1);
            }

            int blockIndex = 0;

            using (var blockCollection = new BlockingCollection <Tuple <RecordsBuffer, int> >(workersCount))
                using (var sortCompletionCollection = new BlockingCollection <bool>(workersCount))
                {
                    Task blocksReadingTask = Task.Factory.StartNew(() =>
                    {
                        do
                        {
                            blockCollection.Add(new Tuple <RecordsBuffer, int>(blocks.Current, blockIndex++));
                            sortCompletionCollection.Add(true);
                        } while (blocks.MoveNext());
                        blockCollection.CompleteAdding();
                    });

                    Task blocksSortingTask = Task.Factory.StartNew(() =>
                    {
                        List <Task> sortTasks = new List <Task>();
                        try
                        {
                            while (true)
                            {
                                Tuple <RecordsBuffer, int> blockAndIndex = blockCollection.Take();

                                Task t = StartBlockSortingTask(blockAndIndex.Item1, blockAndIndex.Item2,
                                                               field, sortCompletionCollection);
                                sortTasks.Add(t);
                            }
                        }
                        catch (InvalidOperationException)
                        {
                            // An InvalidOperationException means that Take() was called on a completed collection
                        }
                        Task.WaitAll(sortTasks.ToArray());
                    });

                    Task.WaitAll(blocksReadingTask, blocksSortingTask);
                }
            return(blockIndex);
        }
Example #2
0
 private Task StartBlockSortingTask(RecordsBuffer block, int blockIndex, int field,
                                    BlockingCollection <bool> sortCompletionCollection)
 {
     return(Task.Factory.StartNew(() =>
     {
         block.Sort(field);
         WriteBlock(block, blockIndex);
         sortCompletionCollection.Take();
         Console.WriteLine($"Block {blockIndex} sorted");
     }));
 }