Лучший способ управлять элементами Listview из потока Indy 10

Я делаю многопользовательский инструмент удаленного администрирования, своего рода VNC, но который поддерживает просмотрщик нескольких удаленных рабочих столов, как и Teamviewer.

У меня есть форма Delphi, которая содержит только TListview, этот список содержит список пользователей, которые в настоящее время подключены к серверу.

Когда соединение разрывается, элемент списка удаляется.

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

Иногда ошибки не появляются, в списке остаются только некоторые элементы, иногда отображаются «ошибки нарушения адреса».

Поскольку я раньше использовал чистый Winsock API для создания клиент-серверного приложения, я, возможно, плохо использую компоненты Indy.

Краткое объяснение моего способа управления серверным компонентом.

Мое приложение - Multi Server, что означает, что пользователь может создавать один или несколько серверов одновременно. Когда новый сервер создается пользователем, он запускает новый поток, который создаст новый компонент indy Server и настроит необходимые события (OnConnect, OnExecute, OnDisconnect) и т. Д.

Все команды, которые действуют с некоторой формой VCL, конечно же, синхронизируются с помощью Synchronize (); delphi метод.

Когда появляется новое соединение, я создаю из метода Server Execute новый элемент listview, а затем устанавливаю новый элемент listview в свойство AContext.data.

Когда соединение разрывается в событии OnDisconnect, я удаляю элемент listview, затем очищаю данные AContext, чтобы быть уверенным, он больше не сделает этого, когда он будет автоматически уничтожен.

Synchronize(procedure begin
TListItem(AContext.data).Delete;
end);
AContext.data := nil;

Этот способ работы очень плохо работает, когда у меня более одного подключения. После отладки кажется, что даже команды Synchronize выполняются одновременно, что может привести к конфликтам в форме VCL.

Я не эксперт в Indy10, любой совет обязательно буду признателен.


person Ricky16    schedule 24.08.2013    source источник
comment
вы можете проверить, не выполняется ли ваш вызов .Delete более одного раза, также вам следует вызвать AContext.Data: = NIL; сразу после .Delete, кроме того, вы ДОЛЖНЫ проверить, есть ли AContext.Data ‹› NIL; Я думаю, ваша проблема в том, что вы плохо храните ссылки на элементы списка, возможно, вы захотите это проверить ... получайте удовольствие! (:   -  person    schedule 24.08.2013


Ответы (1)


Обычно не рекомендуется хранить данные в пользовательском интерфейсе.

Альтернативный ответ о том, как это можно организовать:

  1. Сохраните список пользователей на бизнес-уровне вашего проекта.
  2. Отобразите пользователей с помощью представления списка виртуальной модели, которое получает данные с бизнес-уровня. См., Например, ответ на странице https://stackoverflow.com/a/4233875/29290
  3. Доступ к этим данным потокобезопасным способом (блокировка и т. Д.)
  4. В потоке Indy 10 доступ к данным потокобезопасным способом (блокировка и т. Д.)
  5. Заставьте бизнес-уровень уведомлять части Indy и UI об изменениях данных.
person Jeroen Wiert Pluimers    schedule 24.08.2013