C# Thread.Join()在C中不起作用#

C# Thread.Join()在C中不起作用#,c#,multithreading,join,C#,Multithreading,Join,我有一个CPT项目类和一个CPT类。(CPT是一项测试;通过它我可以获得大量数据)。我想从excel文件中读取CPT数据。但由于它们是大文件,我创建工作读取来同时读取它们。在离开actainCpts()之前,我想确保所有的工作线程都已返回,这就是我对它们调用Join()的原因。但有时仍会显示并非所有workingThreads正在返回的消息(即“not all CPT Acquired!”)。有人能就可能出现的问题给出一些提示吗 public static void ObtainCPTs

我有一个CPT项目类和一个CPT类。(CPT是一项测试;通过它我可以获得大量数据)。我想从excel文件中读取CPT数据。但由于它们是大文件,我创建工作读取来同时读取它们。在离开actainCpts()之前,我想确保所有的工作线程都已返回,这就是我对它们调用Join()的原因。但有时仍会显示并非所有workingThreads正在返回的消息(即“not all CPT Acquired!”)。有人能就可能出现的问题给出一些提示吗

    public static void ObtainCPTs(List<string> fileNames)
    {
        CPTproject.numCPTs = fileNames.Count;

        List<Thread> workingThreads = new List<Thread>() ; 

        for (int i = 0; i < fileNames.Count(); i++)
        {
            HelperClass hp = new HelperClass(fileNames[i]); 

            workingThreads.Add(new Thread(hp.GetCPTdataFromExcel)); 
            workingThreads[i].Start();       
        }

        foreach (Thread t in workingThreads)
        {
            t.Join(); 
        }

        if (CPTproject.CPTs.Count() < CPTproject.numCPTs)
        {
            MessageBox.Show("Not all CPTs obtained!"); 
        }

    }


    class HelperClass
    {
       private string _fileName;

       public helperClass(string fileName)
       {
          this._fileName = fileName;
       }

       public void GetCPTdataFromExcel()
       {
          CPT cpt = new CPT();

          //Reads from excel file with address this._fileName

          CPTproject.CPTs.Add(cpt);
       }
    }
publicstaticvoidactaintcpts(列出文件名)
{
CPTproject.numCPTs=文件名.Count;
List workingThreads=新列表();
对于(int i=0;i
如果
CPTproject.CPTs
不是线程安全的集合,则
Add
方法不是线程安全的。您应该尝试在其周围放置一个

class HelperClass
{
   private object _locker = new object();

   public void GetCPTdataFromExcel()
   {
      CPT cpt = new CPT();

      //Reads from excel file with address this._fileName
      lock (_locker) {
          CPTproject.CPTs.Add(cpt);
       }
   }
}

看起来像是个收藏品。在这种情况下,您可以强制转换到(ICollection)并直接使用SyncRoot,而不是添加另一个对象
lock(((ICollection)CPTproject.SPTs.SyncRoot){}
@ErikNoren实际上这不是一个好主意。如果您这样做,某些集合将抛出一个
NotImplementedException
。@ScottChamberlain框架集合?我并没有全部检查过,但我知道列表确实检查过。syncroot对象周围的代码似乎是以某种方式编写的,以确保对象引用在列表的生命周期内不会更改。再加上一个在代码周围浮动的一次性对象实例。我猜你不能指望第三方代码是一个好公民。我已经试着按照John的建议在CPTproject.CPTs.Add(cpt)上加上锁;但仍然得到同样的错误!但是,锁(((ICollection)CPTproject.SPTs).SyncRoot{}工作正常。我想知道为什么简单的锁不起作用!无论如何,谢谢大家。@ErikNoren有些人将其保留为虚拟成员,其主体设置为NotImplemented,但是他们的派生副本,但是正如您所说的,如果您使用的是派生类的第三方代码,并且没有覆盖虚拟成员,则可能会出现错误。您应该为此使用任务:)