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();
并对结果进行预测和验证。
我写了这样的 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();
并对结果进行预测和验证。