private void ReadTable(IDataReader dataReader, DataTable schemaTable, int tableIndex)
    {
        Assert.IsNotNull(dataReader);
        Assert.IsNotNull(schemaTable);
        Assert.IsInRange(tableIndex >= 0);

        using (LogFactory.Instance.GetCurrentMethodLog())
        {
            Exception exception        = null;
            var       dataReaderHelper = _provider.CreateDataReaderHelper(dataReader);
            var       schemaRows       = schemaTable.Rows;
            var       count            = schemaRows.Count;

            _resultWriter.WriteTableBegin(schemaTable);

            var fieldCount = dataReader.FieldCount;

            if (fieldCount < 0)
            {
                fieldCount = 0;
            }

            var rows = new object[_rowBlockSize][];
            int i;

            for (i = 0; i < _rowBlockSize; i++)
            {
                rows[i] = new object[fieldCount];
            }

            _rowCount = 0;
            i         = 0;
            var first         = true;
            var exitFromWhile = false;
            var stopwatch     = Stopwatch.StartNew();

            while (!_isCommandCancelled && !_thread.IsStopRequested && !exitFromWhile)
            {
                bool read;

                if (first)
                {
                    first = false;
                    _resultWriter.FirstRowReadBegin();
                    read = dataReader.Read();

                    var dataTypeNames = new string[count];

                    if (read)
                    {
                        for (var j = 0; j < count; ++j)
                        {
                            dataTypeNames[j] = dataReader.GetDataTypeName(j);
                        }
                    }

                    _resultWriter.FirstRowReadEnd(dataTypeNames);
                }
                else
                {
                    try
                    {
                        read = dataReader.Read();
                    }
                    catch (Exception e)
                    {
                        read      = false;
                        exception = e;
                    }
                }

                if (read)
                {
                    ++_rowCount;
                    dataReaderHelper.GetValues(rows[i]);
                    ++i;

                    if (i == _rowBlockSize || stopwatch.ElapsedMilliseconds >= 5000)
                    {
                        _resultWriter.WriteRows(rows, i);
                        i = 0;
                        stopwatch.Restart();
                    }

                    if (_rowCount == _maxRecords)
                    {
                        CancelWaitCallback(null);
                        break;
                    }
                }
                else
                {
                    exitFromWhile = true;
                }
            }

            if (i != _rowBlockSize)
            {
                Log.Trace("resultWriter.WriteRows(rows,i);");
                _resultWriter.WriteRows(rows, i);
            }

            Log.Write(LogLevel.Trace, "resultWriter.WriteTableEnd(rowCount);");
            _resultWriter.WriteTableEnd();

            if (_rowCount > 0)
            {
                ++_tableCount;
            }

            if (exception != null)
            {
                throw exception;
            }
        }
    }