代码之家  ›  专栏  ›  技术社区  ›  atamanroman

单线程应用程序显示类似于竞争条件的行为

  •  2
  • atamanroman  · 技术社区  · 14 年前

    我有一个很大的(约40mb)XML数据集合,分为许多格式不好的文件,因此我将它们合并,添加一个根节点,并将所有XML加载到一个文件夹中 XmlDocument

    <Root>
      <A>
        <A>
          <A></A>
          <A></A>
        </A>
      </A>
      <A />
      <B>
        <A>
          <A>
            <A></A>
            <A></A>
          </A>
        </A>
      </B>
      <C />
    </Root>
    

    我通过在A上使用XPath表达式来分离所有A、B和C节点 XML文档 //A , //B , //C ),将生成的节点集转换为datatable,并在Datagridview中分别显示每个节点类型的所有节点的列表。这个很好用。

    XmlDocument.SelectNodes 发生并检查结果 NodeSet . 它显示了大约25000个条目。在继续加载程序并发出呜呜声之后,我的所有25k行都显示出来了。我又试了一次,我可以复制它。如果我走过去XmlDocument.SelectNodes文件用手,就行了。如果我不打破那里,它不会。我没有在我的应用程序中生成一个线程。

    如何进一步调试?找什么?我在jsch(ssh)等多线程库中遇到过这种情况,但我不明白为什么会发生这种情况。

    非常感谢你!

    // class XmlToDataTable:
    private DataTable CreateTable(NamedXPath logType,
                                  List<XmlColumn> columns,
                                  ITableCreator tableCreator)
    {
        // I have to break here -->
        XmlNodeList xmlNodeList = logFile.GetEntries(logType);
        // <-- I have to break here
    
        DataTable dataTable = tableCreator.CreateTableLayout(columns);
        foreach (XmlNode xmlNode in xmlNodeList)
        {
            DataRow row = dataTable.NewRow();
            tableCreator.PopulateRow(xmlNode, row, columns);
            dataTable.Rows.Add(row);
        }
        return dataTable;
    }
    
    // class Logfile:
    public XmlNodeList GetEntries(NamedXPath e)
    {
        return (_xmlDocument != null && _xmlDocument.HasChildNodes)
                             ? _xmlDocument.SelectNodes(e.XPath)
                             : new XmlNullObjectNodeList();
    }
    // _xmlDocument gets loaded here after reading all xml fragments into a string
    // (ugly, i know. the  // ugly! comment reminds me about that ;))
    private void CreateXmlDoc()
    {
        _xmlDocument = new XmlDocument();
        _xmlDocument.LoadXml(OPEN_ROOT_ELEMENT + _xmlString +
                                 CLOSE_ROOT_ELEMENT);
        if (DataChanged != null)
            DataChanged(this, new EventArgs());
    }
    
    // class NamedXPath:
    public abstract class NamedXPath
    {
        private readonly String _name;
        private readonly String _xPath;
        protected NamedXPath(string name, string xPath)
        {
            _name = name;
            _xPath = xPath;
        }
    
        public string Name
        {
            get { return _name; }
        }
    
        public string XPath
        {
            get { return _xPath; }
        }
    }
    
    2 回复  |  直到 14 年前
        1
  •  1
  •   Snak3byte    14 年前

    我将使用诸如 sketchPath 为了让我的XPath正确。可以加载原始XML,也可以使用原始XML的子集。

        2
  •  0
  •   atamanroman    14 年前

    tableCreator 是我策略模式的一部分,它影响表的构建方式。在特定的实现中,我会这样做:

    XmlNode xn = xmlDocument.SelectSingleNode(fancyXPath);
    // if a node has ancestors, then its a linked list:
    // <a><a><a></a></a></a>
    if(xn.SelectSingleNode("a") != null)
        xn.SelectSingleNode("a").InnerText = "<IDs of linked list items CSV like here>";
    

    如果这个改动不会影响到原来的版本,那么找到这个bug就不是问题了 XmlDocument

    返回值: 第一个 匹配XPath查询,如果没有则为null 找到匹配节点。XmlNode 不应期望连接 XML中出现的更改 文档可能不会出现在 XmlNode,反之亦然。(API)

    如果在那里中断,更改将写回原始的XmlDocument,如果不中断,则不会写回原始的XmlDocument。我真的无法向自己解释这一点,但是没有XmlNode中的更改,一切都正常。

    编辑: 现在我很确定:我有XmlNodeList.Count计数在我的手表里。这意味着,每次我调试时,VS调用属性 Count

    internal int ReadUntil(int index)
    {
        int count = this.list.Count;
        while (!this.done && (count <= index))
        {
            if (this.nodeIterator.MoveNext())
            {
                XmlNode item = this.GetNode(this.nodeIterator.Current);
                if (item != null)
                {
                    this.list.Add(item);
                    count++;
                }
            }
            else
            {
                this.done = true;
                return count;
            }
        }
        return count;
    }
    

    这可能导致了这种奇怪的行为。