在线程代码中复制List时出错

时间:2015-01-01 21:55:19

标签: c# multithreading locking

当我的机器负载很重时,我的线程代码出错了。当机器轻载时不会发生错误。我使用的是VS 2013,C#5.0和.NET 4.51。

代码如下:

private static readonly Object lockGetData = new Object();

public static void GetData(string symbol, out List<Tuple<double, double>> velocityLine)
{
   try
   {
      lock (lockGetData)
      {
         mData = mSymbols[symbol];
         Debug.Assert(mData != null, "Oh crap! mData is null");
         velocityLine = new List<Tuple<double, double>>(mData.velocityLine);
         return;
      }
   } 
   catch (Exception ex)
   {
      DebugPrint("GetData error.\n" + ex.Message, symbol);
      velocityLine = new List<Tuple<double, double>>();
      return 0.0;
   } 
}

我收到错误:

velocityLine = new List<Tuple<double, double>>(mData.velocityLine);

错误消息是:“目标数组不够长。检查目标索引和长度,以及数组的下限。”

当错误发生时,当我检查“velocityLine”的长度时,它为空。

我不明白为什么我收到这个错误。任何帮助或建议将不胜感激。

查尔斯

1 个答案:

答案 0 :(得分:2)

如果没有完整的代码示例,则不清楚如何使用mData集合对象。但是在给出错误的情况下,实际上确定在List<T>构造函数执行时,某个其他线程正在修改该对象,结果是该集合的长度在List<T>构造函数使用的时间之间发生变化它初始化后备数组的长度,以及它尝试将所有元素从mData对象复制到后备数组的时间。

仅同步velocityLine对象是不够的。您还必须同步对用于初始化它的mData对象的任何访问。

最后,我会注意到这里有一个try/catch (Exception)子句是非常糟糕的(假设你的版本实际上有一个有效的return语句,而不是这里发布的内容)。如果你把它放在那里只是为了调试这段代码,那很好......但是现在你知道什么是错的,你应该删除它。这将确保如果有任何其他错误,您将被迫修复它们而不是神秘地修改程序,只是在随机时间执行与您想要的不同的操作。