Producer/consumer 没有产生预期的结果

Producer/consumer doesn't generate expected results

我写了这样的 producer/consumer 代码,它应该生成充满随机数据的大文件

    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 个,我不明白为什么会这样。

有人可以指出我的错误吗?我真的不明白这段代码有什么问题。

缓冲区

 String[] block = new string[arrSize];

在 Lambda 之外声明。这意味着它被捕获并 re-used。

这通常会被忽视(你会写出 错误的 随机数据)但是因为你的 if (blockNum < arrSize - 1) 被放置在 for 循环中你经常写一个 null进入共享缓冲区。

锻炼,而不是:

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

使用

block[blockNum] = i.ToString();

并对结果进行预测和验证。