You have a bug in your code which probably causes your SEGFAULT (access violation). The value of TListView.Items.Count is beyond end of list, and the last item is located at *.Count - 1. To get the index of the item which data property holds the client, consider this:
function TMainForm.IndexOfClient(Client: TTCPClient): Integer;
begin
For Result:= 0 To ConnectionListView.Items.Count - 1 Do //Count - 1 = last item
If ConnectionListView.Items[Result].Data = Client Then Exit;
Result:= -1;
end;
Thank you for making me feel extremely stupid. It's been a while since I've programmed in Pascal.
To address the other suggestions (probably useful as I still have another question):
1) I received SIGSEGV even when casting.
2) The thread isn't doing anything with the ListView, it's merely a member of it.
3) In case I needed synchronization I considered using a timer as you've described but I consider the update delay unacceptable.
I've looked more closely at the methods to select an item from a ListView but none of them seem to do what I want. I realized that the ListView probably copies the object for storage. I will need to keep my own record of what is in the list, and the suggestion to use OwnerData seems helpful.
The attempt:
function TMainForm.IndexOfClient(Client: TTCPClient): Integer;
var
I: Integer;
ListClient: TTCPClient;
begin
Result := -1;
for I := 0 to ConnectionListView.Items.Count - 1 do
begin
ListClient := PTCPClient(ConnectionListView.Items[I].Data)^;
WriteLn(ListClient.Host, ':', ListClient.Port);
end;
end;
Fails and prints garbage (no string, very large port). With OwnerData set to true I am unsure of how to manage the ListView - if I need to delete something, do I need to clear it and then re-add every item? If OwnerData is true the loop doesn't run at all.
EDIT: Appears I'll just need to implement the methods referenced in the documentation. Seems rather circuitous - I might just use a separate list and minimally manage the ListView.