【发布时间】:2021-11-01 11:15:12
【问题描述】:
我的 C# 程序做了两个工作:
- 将文件中的记录读入队列 - 每条记录一行
- 从队列中读取数据并对数据进行处理。
该文件有大约 10 亿条记录。每条记录最多 40 个字符。下面的示例代码描述了我在多线程方式中的表现。
//File 1: MessageQueue.cs (Reads data from file into queue)
public class MessageQueue
{
public Queue<string> logQueue = new Queue<string>();
public bool fileread = false;
string textFile = <file name with location>
public void populateQueue()
{
using (StreamReader file = new StreamReader(textFile))
{
string ln;
while (true)
{
while (logQueue.Count < 1000000)
{
ln = file.ReadLine();
if(ln == null)
{
lock (logQueue)
{
fileread = true;
}
file.Close();
break;
}
lock (logQueue)
{
logQueue.Enqueue(ln);
}
}
if (fileread)
break;
Thread.Sleep(1);
}
}
}
}
//File 2: Processes data
public class DoSomething
{
MessageQueue msgQueue;
public DoSomething(MessageQueue msgQueue)
{
this.msgQueue = msgQueue;
}
public void ProcessData()
{
Queue<String> logsQueue = msgQueue.logQueue;
while (true)
{
string logMessage = "";
lock (logsQueue)
{
if (logsQueue.Count != 0)
logMessage = logsQueue.Dequeue();
else if (!msgQueue.fileread)
{
continue; //Queue is empty but there are still records in file
}
else
{
break; //Whole file is read and queue is also empty
}
}
//Do more processing with logMessage
}
File 3: Main
static void Main(string[] args)
{
DateTime startTime = DateTime.Now;
MessageQueue msgQueue = new MessageQueue();
DoSomething doSomething= new DoSomething(msgQueue);
Thread thread1 = new Thread(new ThreadStart(msgQueue.populateQueue));
Thread thread2 = new Thread(new ThreadStart(doSomething.ProcessData));
thread1.Start();
thread2.Start();
DateTime endTime = DateTime.Now;
Console.WriteLine("Time spent in whole loop is " + endTime.Subtract(startTime).TotalMilliseconds);
}
我的想法是确保队列在一个线程中不断填充,而另一个线程正在处理来自队列的数据。另一种方法是顺序读取队列中的 100 万条记录,然后处理该数据,一旦队列为空,再读取 100 万条记录/进程并以这种方式继续,直到不读取整个文件。事实证明,顺序方式比多线程方式更快。我在多线程代码中做错了吗?
【问题讨论】:
-
我们无法调试故事,有很多方法可以让多线程变慢并做错事。也许你可以创建一个小的minimal reproducible example
-
消费者线程如何知道
Queue<T>何时包含足够的数据?它是否将队列集中在一个循环中?您是否在循环中添加了任何Thread.Sleep,或者它正在不停地旋转? -
您是否也只是想解释一下为什么您的并行实现比顺序实现稍慢,或者您想问什么是快速高效地处理这种工作负载的最佳技术?跨度>
标签: c# multithreading