Ошибка Duplicate Key, но не воссоздается при запуске с точками отладки - PullRequest
1 голос
/ 01 июля 2019

Я реализую функцию для добавления некоторых данных в древовидное представление - MVP (приложение состоит из ленты Word (VSTO) + база кода C #).Ниже мой код.

private ElementTreeNode LoadElement(Element element, ElementTreeNode parent = null)
{
    ElementTreeNode loadElement;
    ElementTreeNode node;

    //Add a node to the TreeView that represents the element.
    loadElement = Add(text: GetElementNodeText(element.Name), parent: parent);
    loadElement.Element = element;

    //Add a node to the TreeView for conditions
    if (element.TSS.Conditions.Count > 0)
    {
        Add(text: "Conditions", parent: loadElement).Conditions = element.TSS.Conditions;
    }

    //Add a node to the TreeView control for each image within the element.
    foreach (Image image in element.FrameSets.Active.Images)
    {
        Add(text: GetImageNodeText, parent: loadElement).Image = image;
    }

    //Call this procedure recursively to add any nested elements.
    foreach (Element objElement in element.FrameSets.Active.Elements)
    {
        LoadElement(element: objElement, parent: loadElement);
    }

    return loadElement;
}

Добавить метод:

private ElementTreeNode Add(string text, string key = "", ElementTreeNode parent = null)
{
    try
    {
        TreeNode node = null;
        //Create a random key if a key is not specified.
        if (key.Length == 0)
        {
            key = "ElementTreeNode_" + GetRandomNumber();
        }

        //Add a node to the TreeView control.
        if (parent == null) //..............point 1
        {
            node = treeView.Nodes.Add(key: key, text: text);
        }
        else // ..............point 2
        {
            node = parent.Node.Nodes.Add(key: key, text: text);
        }
        //Add a new ElementTreeNode object to this collection. It will have the same key as objNode.
        ElementTreeNode objNode = new ElementTreeNode(node);                
        elementTreeNodesCollection.Add(key: key, value: objNode);

        return objNode;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message + Environment.NewLine + "ElementTreeNodes.Add","MyApp,
                 MessageBoxButtons.OK, MessageBoxIcon.Error);
        return null;
    }
}

Создать случайное число:

public long GetRandomNumber()
{
    Random rnd = new Random();
    return rnd.Next();
}

Проблема в том, что в моем тестовом прогоне этот код сначала добавляет родительский элементв виде дерева и добавлен в коллекцию (Dictionary<string, ElementTreeNode> elementTreeNodesCollection).На следующем шаге узел дерева условий будет добавлен как узел под родительским элементом к узлу дерева.Когда я пытаюсь добавить его к elementTreeNodesCollection, выдает ошибку ниже.

Элемент с таким же ключом уже добавлен

Самая большая проблема, если я поставлю точки отладки на точка 1 или раньше (нетдругие точки отладки во всей кодовой базе) в методе Add, я не получаю никаких ошибок, и элементы были добавлены в древовидное представление и коллекцию хорошо.

Но если я добавлю точку отладки в или после точка 2 , я получу ошибку.Кроме того, когда нет точек останова, я также получил эту ошибку.

Я попытался установить ключ в качестве возрастающего числа, а затем код работал нормально.Но мне нужно здесь использовать случайное число, поскольку метод LoadElement связан с рекурсией.Эта проблема связана с функцией генерации случайных чисел?или другой случай?Я действительно застрял здесь.

Кто-нибудь имеет представление о том, что я здесь делаю неправильно?

Заранее спасибо.

1 Ответ

4 голосов
/ 01 июля 2019

Я сильно подозреваю, что проблема в вашем GetRandomNumber() методе, который зависит от текущего времени. Если вы наберете его несколько раз подряд, вы получите один и тот же номер.

Если вы ждете немного между вызовами - например, из-за остановки в точке останова - вы получите разные случайные числа.

Я бы предположил, что самым простым вариантом было бы вообще сделать число не случайным - сохранить счетчик, который вы увеличиваете каждый раз, когда вам нужно создать новый ключ. Или вы можете использовать Guid.NewGuid() и преобразовать это в строку, или что-то подобное.

Если вы действительно хотите использовать Random, создайте один экземпляр Random, который вы используете для всех вызовов, но имейте в виду, что Random не является поточно-ориентированным; если вам нужно работать в нескольких потоках, все становится намного сложнее.

...