Производитель / потребитель не дает ожидаемых результатов - PullRequest
0 голосов
/ 09 июля 2019

Я написал такой код производителя / потребителя, который должен генерировать большой файл, заполненный случайными данными

    class Program
    {
        static void Main(string[] args)
        {
            Random random = new Random();
            String filename = @"d:\test_out";
            long numlines = 1000000;
            var buffer = new BlockingCollection<string[]>(10); //limit to not get OOM.
            int arrSize = 100; //size of each string chunk in buffer;        
            String[] block = new string[arrSize];
            Task producer = Task.Factory.StartNew(() =>
            {
                long blockNum = 0;
                long lineStopped = 0;
                for (long i = 0; i < numlines; i++)
                {
                    if (blockNum == arrSize)
                    {
                        buffer.Add(block);
                        blockNum = 0;
                        lineStopped = i;
                    }
                    block[blockNum] = random.Next().ToString();
                    //null is sign to stop if last block is not fully filled
                    if (blockNum < arrSize - 1)
                    {
                        block[blockNum + 1] = null;
                    }
                    blockNum++;
                };
                if (lineStopped < numlines)
                {
                    buffer.Add(block);
                }
                buffer.CompleteAdding();
            }, TaskCreationOptions.LongRunning);
            Task consumer = Task.Factory.StartNew(() =>
            {
                using (var outputFile = new StreamWriter(filename))
                {
                    foreach (string[] chunk in buffer.GetConsumingEnumerable())
                    {
                        foreach (string value in chunk)
                        {
                            if (value == null) break;
                            outputFile.WriteLine(value);
                        }
                    }
                }
            }, TaskCreationOptions.LongRunning);
            Task.WaitAll(producer, consumer);
        }
    }

И он делает то, что намеревается сделать. Но по неизвестной причине он производит только ~ 550000 строк, а не 1000000, и я не могу понять, почему это происходит.

Может кто-нибудь указать на мою ошибку? Я действительно не понимаю, что не так с этим кодом.

1 Ответ

2 голосов
/ 09 июля 2019

Буфер

 String[] block = new string[arrSize];

объявлен вне лямбды.Это означает, что он захвачен и используется повторно.

Обычно это остается незамеченным (вы просто записываете неправильные случайные данные), но поскольку ваш if (blockNum < arrSize - 1) помещается в цикл for, вы регулярно записываете null в общий ресурс.буфер.

Упражнения вместо:

block[blockNum] = random.Next().ToString();

используйте

block[blockNum] = i.ToString();

и прогнозируйте и проверяйте результаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...