c #: получение в очереди делегатов в списке вызовов элементов управления - PullRequest
4 голосов
/ 25 мая 2011

Предположим, мне нужно взять древовидную структуру и добавить некоторые узлы BFS , но также и потокобезопасным способом.

treeView.Invoke((MethodInvoker)delegate{treeView.Nodes.Add(someNode);});

Позже я хотел бы добавить узел к одному из узлов, добавленных в treeView (так как моя глубина увеличивается на один). Откуда мне знать, что у treeView были добавлены все его глубины на один узел перед добавлением второго слоя узлов. Кстати, информация на втором уровне зависит от первого уровня. Все это только пример того, что мне нужно, но это вторично по отношению к реальному вопросу.

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

Как я могу выполнить любую из этих задач?

Полагаю, я мог бы сначала добавить узлы по глубине, но не хочу. Есть ли лучший способ?

Я действительно ненавижу идею, что очередь сообщений / делегатов формируется под капотом, и я не могу ее контролировать.

1 Ответ

1 голос
/ 25 мая 2011

Как делегаты ставятся в очередь под капотом

Фактические делегаты хранятся в очереди в закрытом поле с именем threadCallbackList в элементе управления или ближайшем родительском элементе управления, дескриптор которого уже создан.Структура данных - это просто System.Collections.Queue.

Зная, что в TreeView добавлены все его узлы глубины 1

Если вы хотите общаться с основным потоком, который имел узелвсе это заполненные потомки, вы можете хранить что-то (перечисление) в свойстве Tag узла, чтобы указать это.

Если вы думаете, что вам нужно связаться с фоновым потоком, который выполнил делегат, который добавляет последний узел к уровню древовидного представления, вы этого не делаете.Делегаты, отправленные вами с помощью BeginInvoke и Invoke, будут выполняться по порядку.

Прерывание выполнения BeginInvoke d делегатов

Невозможно прервать выполнение делегатов, поставленных в очередьв потоке пользовательского интерфейса от нажатия на элемент управления в том же потоке.Выполнение делегата, как и любая другая часть вашей программы.Это цикл, который исключает из очереди каждого из делегатов и выполняет их.Ваш поток пользовательского интерфейса будет выполнять эти делегаты, поэтому он также не сможет выполнить обработчик события click, который попытался бы прервать выполнение делегатов, поставленных в очередь.Даже если бы вы могли понять, как использовать отражение, чтобы связываться с делегатами в очереди, вы не могли бы сделать это в то же время , что другой код выполняет в том же потоке.

Возможное решение

Похоже, вы просто беспокоитесь о том, чтобы забить поток пользовательского интерфейса.Если это так, вы можете задушить фоновый поток, вызывая Invoke вместо BeginInvoke каждый вызов N th .Это заставит ваш фоновый рабочий поток ждать, пока очередь не очистится (по крайней мере, до делегата, переданного в этом вызове).Таким образом, вы никогда не получите больше чем N делегатов в очереди за раз.Если вы пошли по этому маршруту, вы могли бы просто Invoke каждый раз и использовать AddRange(someNodes) вместо Add(someNode).

...