有什么方法可以自动检查列表项的存在和列表项的调用方法吗?

mbe*_*ish -2 .net c# multithreading

我有一个线程列表,我正在尝试让我的主线程等待列表中的所有线程终止:

while (consumers.Count > 0) consumers[0].Join();
Run Code Online (Sandbox Code Playgroud)

问题是,这不是原子的,我可以得到一个"索引超出范围"的例外.

有没有任何原子方法来检查消费者[0]的存在并调用消费者[0] .Join()?

注意:我做不到

lock (myLocker) { if (consumers.Count > 0) consumers[0].Join(); }
Run Code Online (Sandbox Code Playgroud)

因为我不想阻止其他线程在加入Join()时访问消费者.

Jon*_*eet 5

好吧,如果您没有应用任何同步,但是您的列表正在从多个线程进行修改,那么您已经遇到了麻烦.其他一切都用myLocker吗?假设它确实如此,那么:

while(true)
{
    List<Thread> copy;
    lock (myLocker)
    {
        copy = new List<Thread>(consumers);
    }
    if (copy.Count == 0)
    {
        break;
    }
    foreach (Thread thread in copy)
    {
        thread.Join();
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,这consumers在持有锁时访问,这是您应该在任何地方执行以实现线程安全的操作.它还Join在复制之后调用所有线程,而不是仅为每次迭代执行一次.

如果你知道此时线程不会被添加到列表中(例如,它是一个正在耗尽的线程池),你可以删除循环和检查:

    List<Thread> copy;
    lock (myLocker)
    {
        copy = new List<Thread>(consumers);
    }
    foreach (Thread thread in copy)
    {
        thread.Join();
    }
Run Code Online (Sandbox Code Playgroud)

  • @mbeckish:你的副本将*总是*在你访问它时立即变得陈旧 - 你对Thread.Join的直觉是不正确的,如记录所示:"如果在调用Join时线程已经终止,则该方法立即返回." 鉴于您无法原子地"检查线程状态并调用Join"任何Join API,如果线程已经终止则会因设计而中断异常. (2认同)