public static void GetSomeLines(IMultiStreamSource source, int count, ref List <DvText> lines)
            {
                Contracts.AssertValue(source);
                Contracts.Assert(count > 0);
                Contracts.AssertValueOrNull(lines);

                if (count < 2)
                {
                    count = 2;
                }

                LineBatch batch;
                var       reader = new LineReader(source, count, 1, false, count, 1);

                try
                {
                    batch = reader.GetBatch();
                    Contracts.Assert(batch.Exception == null);
                    if (Utils.Size(batch.Infos) == 0)
                    {
                        return;
                    }
                }
                finally
                {
                    reader.Release();
                }

                for (int i = 0; i < batch.Infos.Length; i++)
                {
                    Utils.Add(ref lines, new DvText(batch.Infos[i].Text));
                }
            }
            public static void GetSomeLines(IMultiStreamSource source, int count, bool readMultilines, char[] separators, char escapeChar, ref List <ReadOnlyMemory <char> > lines)
            {
                Contracts.AssertValue(source);
                Contracts.Assert(count > 0);
                Contracts.AssertValueOrNull(lines);

                if (count < 2)
                {
                    count = 2;
                }

                LineBatch batch;
                var       reader = new LineReader(source, count, 1, false, readMultilines, separators, escapeChar, count, 1);

                try
                {
                    batch = reader.GetBatch();
                    Contracts.Assert(batch.Exception == null);
                    if (Utils.Size(batch.Infos) == 0)
                    {
                        return;
                    }
                }
                finally
                {
                    reader.Release();
                }

                for (int i = 0; i < batch.Infos.Length; i++)
                {
                    Utils.Add(ref lines, batch.Infos[i].Text.AsMemory());
                }
            }
                private void Parse(int tid)
                {
                    long blk  = tid;
                    int  iblk = tid;

                    Contracts.Assert(iblk < _blockCount - 3);

                    var helper = _curs._parser.CreateHelper(_rows.Stats, _curs._srcNeeded);

                    while (!_done)
                    {
                        // Algorithm:
                        // * When it is our turn, grab a block of lines.
                        // * Parse rows.
                        // * When it is our turn, enqueue the batch.

                        // When it is our turn, read the lines and signal the next worker that it is ok to read.
                        LineBatch lines;
                        _waiterReading.Wait(blk);
                        if (_done)
                        {
                            return;
                        }
                        try
                        {
                            lines = _reader.GetBatch();
                        }
                        finally
                        {
                            _waiterReading.Increment();
                        }
                        Contracts.Assert(lines.Exception == null);
                        if (lines.Infos == null || _done)
                        {
                            return;
                        }

                        // Parse the lines into rows.
                        Contracts.Assert(lines.Infos.Length <= BlockSize);

                        var batch = new RowBatch(iblk * BlockSize, iblk * BlockSize + lines.Infos.Length, lines.Total);
                        int irow  = batch.IrowMin;
                        foreach (var info in lines.Infos)
                        {
                            Contracts.Assert(info.Line > 0);
                            Contracts.AssertNonEmpty(info.Text);
                            if (_done)
                            {
                                return;
                            }
                            _curs._parser.ParseRow(_rows, irow, helper, _curs._active, lines.Path, info.Line, info.Text);
                            irow++;
                        }
                        Contracts.Assert(irow == batch.IrowLim);

                        if (_done)
                        {
                            return;
                        }

                        // When it is our turn, publish the rows and signal the next worker that it is ok to publish.
                        _waiterPublish.Wait(blk);
                        if (_done)
                        {
                            return;
                        }
                        while (!_queue.TryAdd(batch, TimeOut))
                        {
                            if (_done)
                            {
                                return;
                            }
                        }
                        _waiterPublish.Increment();

                        blk  += _threads.Length;
                        iblk += _threads.Length;
                        if (iblk >= _blockCount)
                        {
                            iblk -= _blockCount;
                        }
                        Contracts.Assert(0 <= iblk && iblk < _blockCount);
                    }
                }