Возможная проблема Threading / COM / UI
-
04-07-2019 - |
Вопрос
Я пишу панель инструментов для IE (6+). Я использовал различные образцы баров из
codeproject.com ( http://www.codeproject.com/KB/dotnet /IE_toolbar.aspx ) и иметь панель инструментов, которая работает, регистрирует отмены регистрации и т. Д. Я хочу, чтобы панель инструментов выделяла элементы div на странице html при перемещении мыши пользователя над этим элементом div. Пока код подсветки работает, но я хотел бы отобразить имя div (если оно существует) в метке на панели инструментов (меняется при перемещении мыши и т. Д.).
Я не могу на всю жизнь заставить это случиться, и попытка отладки - это кошмар. Поскольку сборка размещается в IE, я подозреваю, что я вызываю исключение (в IE), пытаясь обновить текст на метке из потока, который не создал этот элемент управления, но поскольку это исключение происходит в IE, я не вижу этого Р>
Является ли решение попытаться обновить элемент управления потокобезопасным способом с помощью Invoke? Если так, то как?
Вот код события:
private void Explorer_MouseOverEvent(mshtml.IHTMLEventObj e)
{
mshtml.IHTMLDocument2 doc = this.Explorer.Document as IHTMLDocument2;
element = doc.elementFromPoint(e.clientX, e.clientY);
if (element.tagName.Equals("DIV", StringComparison.InvariantCultureIgnoreCase))
{
element.style.border = "thin solid blue;";
if (element.className != null)
{
UpdateToolstrip(element.className);
}
}
e.returnValue = false;
}
и вот попытка поточно-ориентированного обновления панели инструментов:
delegate void UpdateToolstripDelegate(string text);
public void UpdateToolstrip(string text)
{
if (this.toolStripLabel1.InvokeRequired == false)
{
this.toolStripLabel1.Text = text;
}
else
{
this.Invoke(new UpdateToolstripDelegate(UpdateToolstrip), new object[] { text });
}
}
Любые предложения очень ценятся.
Решение
Я не могу воспроизвести проблему (создание тестового проекта для панели инструментов IE - это слишком много работы), но вы можете попробовать это:
Добавьте следующую подпрограмму в открытый статический класс (методы расширений):
public static void Invoke(this Control control, MethodInvoker methodInvoker)
{
if (control.InvokeRequired)
control.Invoke(methodInvoker);
else
methodInvoker();
}
А затем замените раздел аналогичного кода в первом блоке следующим образом:
if (element.className != null)
{
this.Invoke(() => toolStripLabel1.Text = element.className);
}
Это верный способ избежать поточно-ориентированных проблем в приложениях пользовательского интерфейса.