【问题标题】:Thread.Join() not working in C#Thread.Join() 在 C# 中不起作用
【发布时间】:2014-04-29 15:32:40
【问题描述】:

我有一个 CPTproject 课程和一个 CPT 课程。 (CPT 是一项测试;这样做我得到了很多数据)。我想从 excel 文件中读取 CPT 数据。但由于它们是大文件,我正在创建 workingThreads 以一致地阅读它们。我想在我离开ObtainCPTs() 之前确保所有工作线程都已返回,这就是我对它们调用Join() 的原因。但有时仍会显示并非所有工作线程都返回(即“并非所有 CPTs 获得!”)消息。任何人都可以就可能出现的问题给出一些提示吗?

    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);
       }
    }

【问题讨论】:

  • 你应该为此使用任务:)

标签: c# multithreading join


【解决方案1】:

如果CPTproject.CPTs 不是线程安全集合,则Add 方法不是线程安全的。你应该尝试在它周围加上lock

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 实际上这不是一个好主意。如果您这样做,某些集合会抛出NotImplmentedException
  • @ScottChamberlain 框架的?我还没有全部检查过,但我知道 List 确实如此。围绕 syncroot 对象的代码似乎以确保对象引用在列表的生命周期内永远不会更改的方式编写。再加上少了一个漂浮在您的代码周围的一次性对象实例。我猜你不能指望 3rd 方代码成为一个好公民。
  • 我已尝试按照 John 的建议将锁放在 CPTproject.CPTs.Add(cpt) 周围;但仍然得到同样的错误!但是, lock(((ICollection)CPTproject.SPTs).SyncRoot) { } 工作正常。我想知道为什么简单的锁不起作用!无论如何,谢谢大家。
  • @ErikNoren 一些 base classes 将其保留为虚拟成员,主体设置为 NotImplmented,但它们的派生对应物 do override them,但就像你说的,如果你正在使用派生的第 3 方代码类并且不会覆盖您可能会收到错误的虚拟成员。
猜你喜欢
  • 2016-03-28
  • 1970-01-01
  • 2023-02-22
  • 1970-01-01
  • 1970-01-01
  • 2011-06-03
  • 1970-01-01
  • 1970-01-01
  • 2021-08-04
相关资源
最近更新 更多