Ошибка при динамическом создании 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);