Ошибка при динамическом создании toolStripMenuItem

У меня следующая проблема: у меня есть файл конфигурации и прослушиватель для этого файла. При изменении запускает метод (createMenuAndItems), который изменяет toolStripMenuItem,

Метод createMenuAndItems вызывается при загрузке формы и при изменении файла конфигурации. Всякий раз, когда массив

strArrays = new string[] { "Copy File" ,  "Exit"};

имеет более одного элемента, показывает ошибку при изменении файла конфигурации. при загрузке форма работает нормально.

Ошибка, как показано в Visual Studio:

System.InvalidOperationException не было обработано

HResult=-2146233079
Сообщение =: операция между потоками недопустима: элемент управления 'topMenu' доступен из потока, отличного от потока, в котором он был создан

Фактическое сообщение

Сообщение = Операция без предоставления информации о подпроцессе: Отдельный контроль над "верхним меню" и подпрограммой, отличной от всех остальных.

Источник =System.Windows.Forms
Трассировки стека:

Пробовал с CheckForIllegalCrossThreadCalls = False; но не повезло

Странно то, что если массив strArrays имеет только одно значение, оно работает как шарм. но при добавлении большего количества элементов начинает отображаться эта ошибка

Вот код

Слушатель над файлом:

    private void configWatcher()
    {
        FileSystemWatcher fileSystemWatcher = new FileSystemWatcher()
        {
            Path = string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "\\Launcher"),
            Filter = "Config.xml"
        };
        fileSystemWatcher.Changed += new FileSystemEventHandler(this.createMenuAndItems);
        fileSystemWatcher.EnableRaisingEvents = true;
    }

Вот код, который создает и изменяет toolStripMenuItem

private void createMenuAndItems()
{
    string str;
    ToolStripMenuItem toolStripMenuItem;
    int i;
    base.Invoke(new Action(() =>
    {
        base.Controls.Find("topMenu", false);
        if (base.Controls.IndexOfKey("topMenu") > 0)
        {
            base.Controls.RemoveByKey("topMenu");
        }
    }));
    MenuStrip menuStrip = new MenuStrip()
    {
        Name = "topMenu"
    };
    base.Invoke(new Action(() => this.Controls.Add(menuStrip)));
    string[] strArrays = new string[] { "Menú" };
    string[] array = strArrays;
    for (i = 0; i < (int)array.Length; i++)
    {
        ToolStripMenuItem toolStripMenuItem1 = new ToolStripMenuItem(array[i]);
        menuStrip.Items.Add(toolStripMenuItem1);
    }
    foreach (ToolStripMenuItem item in menuStrip.Items)
    {
        if (item.Text == "Menú")
        {
            strArrays = new string[] { "Copy File" ,  "Exit"};
            array = strArrays;                    
            for (i = 0; i < (int)array.Length; i++)
            {
                str = array[i];
                toolStripMenuItem = new ToolStripMenuItem(str, null, new EventHandler(this.ChildClick));
                item.DropDownItems.Add(toolStripMenuItem);
            }
            foreach (ToolStripMenuItem dropDownItem in item.DropDownItems)
            {
                if (dropDownItem.Text == "Copy File")
                {
                    //gives a list of strings.
                    array = this.fetchServersFromConfig().ToArray();
                    for (i = 0; i < (int)array.Length; i++)
                    {
                        str = array[i];
                        toolStripMenuItem = new ToolStripMenuItem(string.Concat("Origin: ", str), null, new EventHandler(this.copyFile));
                        dropDownItem.DropDownItems.Add(toolStripMenuItem);
                    }
                }
                if (dropDownItem.Text == "Exit")
                {                            
                    dropDownItem.ShortcutKeys = Keys.Control | Keys.Q;
                    dropDownItem.Click += new EventHandler(this.exitButtonMenu);
                }
            }
        }
    }
}

Спасибо!

1 ответ

Наконец, решил эту проблему, вызвав создание меню и пунктов через главный поток внутри configWatcher()

Как это:

fileSystemWatcher.Changed += new FileSystemEventHandler(base.Invoke(new Action(() => this.createMenuAndItems())););

Вместо:

fileSystemWatcher.Changed += new FileSystemEventHandler(this.createMenuAndItems);
Другие вопросы по тегам