从另一个线程检查线程结束

时间:2011-08-10 05:59:40

标签: .net multithreading

我有一个通过TcpClient从端口读取数据的类。我创建了2个线程。

  1. 数据包阅读线程
  2. 数据包处理线程
  3. 1线程连续读取字节,一旦获得正确的数据包,它就会在队列中添加该数据包并启动第二个线程,然后从该队列中读取数据包并对其进行处理。

    数据包处理应按顺序进行。因此,每当读取线程在队列中添加数据包时,它都会检查处理线程是否正在运行。如果不是,那么它再次启动该线程。这是因为我们不希望同时运行多个数据包处理线程。

    现在我的问题实际上与检查部分有关。我所做的是,我在课堂上添加了一个简单的bool变量。当我进入数据包处理线程时,我设置了bool = true。数据包读取线程检查此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的原因 OR
    *)它应该以某种方式被阻止,直到没有收到另一个数据包。

4 个答案:

答案 0 :(得分:2)

你肯定有一个竞争条件,没有任何锁定比描述。如果两个数据包快速连续进入,您可能会看到该标志为假两次并启动两个不同的线程。您可以通过使读取线程在启动线程时将标志设置为false来避免这种情况 - 因此该标志表示“线程正在运行或正在启动”。

目前还不清楚为什么你还需要继续启动线程 - 为什么不只是让一个处理线程在队列为空时阻塞等待新数据包?如果您使用的是.NET 4,那么使用BlockingCollection<T>非常容易。

编辑:如果您不需要按特定顺序处理数据包,则可以为每个数据包启动一个新的线程池工作项:

ThreadPool.QueueUserWorkItem(ProcessPacket, packet);

...

private void ProcessPacket(object state)
{
    Packet packet = (Packet) state;
    ...
}

答案 1 :(得分:2)

您可能需要考虑使用BlockingCollection<T>类。您的处理线程将阻止等待下一个项目入队。

有人建议阅读:Threading in C#

答案 2 :(得分:0)

另一种设计是使用wait handle代替并等到它在调用处理之前发出信号 - 可能在CPU方面更好。

答案 3 :(得分:0)

首先,你应该避免使用“共享Resssources”这意味着,数据,属性,...在多个线程上使用。

如果你使用它们,你应该同步它们(s。ReaderWriterLockSlim

还有一些名为TPL的扩展类使得更容易使用线程。请参阅此示例link

如果您使用TPL,那么您可以使用Task Class作为完成任务的等待方法。

- &GT;任务myTask = Task.Factory.StartNew(()=&gt; Foo());

        myTask.Wait();

我总是使用TPL或至少使用Threadpool进行多线程处理。

你也可以考虑使用RX,它在Thread和linq上有某种统一的编程模型