【发布时间】:2011-08-10 15:24:59
【问题描述】:
我有一个通过 TcpClient 从端口读取数据的类。我创建了 2 个线程。
- 数据包读取线程
- 数据包处理线程
1 线程连续读取字节,一旦它得到一个正确的数据包,它就会将该数据包添加到队列中并启动第二个线程,然后从该队列中读取数据包并进行处理。
数据包处理应按顺序进行。因此,每次读取线程将数据包添加到队列中时,它都会检查该处理线程是否正在运行。如果不是,那么它会再次启动该线程。这是因为我们不希望多个数据包处理线程同时运行。
现在我的问题实际上与检查部分有关。我所做的是,我在课堂上添加了一个简单的 bool 变量。当我进入数据包处理线程时,我设置了 bool = true。当数据包读取线程检查这个布尔变量时,如果它是真的,那么它知道处理线程正在运行。当数据包处理线程到达结束时,它设置 bool = false。
这是正确的方法吗?还是这种方法容易出现竞争条件?
谢谢。
更新(一点细节):
delegate void PacketProcessDelegate();
PacketProcessDelegate PacketProcess = new PacketProcessDelegate(this.PacketProcessingThread);
PacketReadingThread() {
Packet = GetPacket(); // thread blocks until packet is NOT received
Queue.Synchronized(this.Queue).Enque(Packet);
if (!this.IsProcessing)
this.PacketProcess.BeginInvoke(null, null);
}
PacketProcessingThread() {
this.IsProcessing=true;
while(true) {
Queue syncQueue;
syncQueueu = Queue.Synchronized(this.Queue);
if(syncQueueu.Count > 0)
//packet extraction and processing code here
else
break;
}
this.IsProcessing=false;
}
目标:
数据包处理线程或者
*) 应该被终止并应该重新启动,但应该使用 ThreadPool 以防止每次创建新线程。这就是我使用 BeginInvoke 的原因。
或
*) 它应该以某种方式被阻止,直到没有收到另一个数据包。
【问题讨论】:
-
有什么理由不能简单地使用Thread.IsAlive 属性?
-
处理一个数据包后是否需要结束处理线程?如果没有,你可以继续运行处理线程,如果队列为空,它应该等待。
-
@drharris:实际上新线程是使用 BeginInvoke() 方法调用的。它实际上不是 Thread 变量。
-
BeginInvoke()不会启动新线程。它调用调度程序或 UI 线程上的操作。 -
实际上,忘记了
Delegate.BeginInvoke(),它确实启动了一个线程池线程。不过,如果您需要跟踪线程生命周期,这可能不是最佳实践。在这种情况下最好使用Thread,并考虑使用BlockingCollection<T>,正如乔恩和我自己所建议的那样。
标签: .net multithreading