public void Close()
 {
     if (_externalReader != null)
     {
         _externalReader.Close();
         _externalReader.Dispose();
         _externalReader = null;
     }
 }
        private void FillRest <TInnerType>(long step, IExternalReader <TInnerType> reader,
                                           IExternalWriter <TInnerType> writer, TInnerType student)
            where TInnerType : class, IComparable
        {
            var localStep    = step;
            var localStudent = student;

            while (localStudent != null)
            {
                writer.Write(localStudent);
                localStep--;
                localStudent = ReadNextStudentInPhase(localStep, reader, null);
            }
        }
        ///// <summary>
        ///// Фаза слияния, сливаем из двух источников в один документ, попутно получая сортированный фазы длинной step * 2
        ///// </summary>
        ///// <param name="readerOne">Первый источник</param>
        ///// <param name="readerTwo">Второй источник</param>
        ///// <param name="writer">получатель</param>
        ///// <param name="step">Длина исходной сортированной фазы</param>
        private void Merge <TInnerType>(IExternalReader <TInnerType> readerOne, IExternalReader <TInnerType> readerTwo,
                                        IExternalWriter <TInnerType> writer, long step)
            where TInnerType : class, IComparable
        {
            while (true)
            {
                if (!readerOne.IsCanRead && !readerTwo.IsCanRead)
                {
                    return;
                }

                DoPhase(readerOne, readerTwo, writer, step);
            }
        }
        private TInnerType ReadNextStudentInPhase <TInnerType>(long step, IExternalReader <TInnerType> reader,
                                                               TInnerType currentStudent)
            where TInnerType : class, IComparable
        {
            if (step <= 0)
            {
                return(null);
            }

            if (currentStudent != null)
            {
                return(currentStudent);
            }

            return(reader.IsNext() ? reader.Current : null);
        }
 /// <summary>
 /// Фаза разделения, разделяем данный на два файла по сортированным фазам длинной step
 /// </summary>
 /// <param name="reader">Источник</param>
 /// <param name="writerOne">Первый получатель</param>
 /// <param name="writerTwo">Второй получатель</param>
 /// <param name="step">Длина сортированной фазы</param>
 private void Devision <TInnerType>(IExternalReader <TInnerType> reader, IExternalWriter <TInnerType> writerOne,
                                    IExternalWriter <TInnerType> writerTwo, long step)
     where TInnerType : class, IComparable
 {
     while (reader.IsNext())
     {
         writerOne.Write(reader.Current);
         for (long i = 1; (i < step) && reader.IsNext(); i++)
         {
             writerOne.Write(reader.Current);
         }
         for (long i = 0; (i < step) && reader.IsNext(); i++)
         {
             writerTwo.Write(reader.Current);
         }
     }
 }
        private void DoPhase <TInnerType>(IExternalReader <TInnerType> readerOne, IExternalReader <TInnerType> readerTwo,
                                          IExternalWriter <TInnerType> writer, long step)
            where TInnerType : class, IComparable
        {
            var stepOne = step;
            var stepTwo = step;

            TInnerType currentFirst  = null;
            TInnerType currentSecond = null;

            while (true)
            {
                currentFirst  = ReadNextStudentInPhase(stepOne, readerOne, currentFirst);
                currentSecond = ReadNextStudentInPhase(stepTwo, readerTwo, currentSecond);

                if (currentFirst == null && currentSecond == null)
                {
                    return;
                }

                if (currentFirst == null && currentSecond != null)
                {
                    FillRest(stepTwo, readerTwo, writer, currentSecond);
                    return;
                }

                if (currentFirst != null && currentSecond == null)
                {
                    FillRest(stepOne, readerOne, writer, currentFirst);
                    return;
                }

                if (currentFirst.CompareTo(currentSecond) > 0)
                {
                    writer.Write(currentSecond);
                    stepTwo--;
                    currentSecond = null;
                }
                else
                {
                    writer.Write(currentFirst);
                    stepOne--;
                    currentFirst = null;
                }
            }
        }
        public void Open()
        {
            if (_externalReader != null)
            {
                throw new InvalidOperationException("Reader already opened");
            }

            try
            {
                _externalReader = ReaderLocator.GetReader(_source, _behavior);
                _externalReader.Open();

                TotalCount = _externalReader.RecordsCount;
            }
            catch (Exception ex)
            {
                Log.Exception(ex);
                Close();
                _buffer.Finish();
            }
        }