межпотоковая операция даже при выполнении в потоке пользовательского интерфейса - PullRequest
2 голосов
/ 23 июля 2010

У меня есть функция, которая добавляет элемент управления к родительскому элементу управления, который вызывается из потоков, отличных от потока, в котором были созданы элементы управления.Вот как это происходит:

1        delegate void AddControlToParentDelegate(Control child, Control parent);
2        private void addControlToParent(Control child, Control parent) {
3        if (parent.InvokeRequired) {
4            AddControlToParentDelegate d = new  AddControlToParentDelegate(addControlToParent);
5            this.Invoke(d, new object[] { child, parent });
6            } else {
7                parent.Controls.Add(child);
8            }
9        }
10    }

Это работает до тех пор, пока оба значения parent.InvokeRequired и child.InvokeRequired не станут ИСТИНАМИ.Затем, как только строка 5 выполняется (теперь вызывается делегат d и предполагается, что функция выполняется в потоке пользовательского интерфейса. (Верно?)) child в строке 7 выдает недопустимое исключение операции межпотоковой операции.Почему это?Разве он не запущен в потоке, в котором он был создан?

Мне удалось это исправить, добавив дополнительную (child.InvokeRequired) проверку:

delegate void AddControlToParentDelegate(Control child, Control parent);
private void addControlToParent(Control child, Control parent) {
    if (parent.InvokeRequired) {
        AddControlToParentDelegate d = new AddControlToParentDelegate(addControlToParent);
        this.Invoke(d, new object[] { child, parent });
    } else {
        if (child.InvokeRequired) {
            this.Invoke(new MethodInvoker(delegate() {
            parent.Controls.Add(child);
            }));
        } else {
            parent.Controls.Add(child);
        }
    }
}

, но это просто ужасно выглядити не нужно.Это способ сделать это?Или я полностью опоздал на автобус?

1 Ответ

6 голосов
/ 23 июля 2010

Обратите внимание, что InvokeRequired ненадежен, когда элемент управления не имеет дескриптора окна. Это почти наверняка относится к вновь созданному дочернему элементу управления, у которого еще нет родителя, что, как представляется, имеет место в вашем «фиксированном» коде.

См. Подробный анализ Ивана Кривякова: http://www.ikriv.com/en/prog/info/dotnet/MysteriousHang.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...