Active
to false, it already disconnects the clients for you, and then waits for their threads to terminate. Your issue is that your code is blocking the threads from terminating correctly. That is what you need to fix properly, not hack around it.
procedure TForm2.Log(const s: string);
begin
mLog.Lines.Add(s);
end;
@elekgeek your Log()
function is directly accessing a UI component (a TMemo
?). THAT IS NOT THREAD-SAFE! That could easily cause deadlocks (amongst many other problems). OnExecute
is fired in a worker thread, so Log()
MUST synchronize with the main UI thread. I suggest it use TThread.Queue()
or TIdNotify
for that purpose (depending on your version of Delphi). That would avoid any cross-thread access issues, avoid any deadlock scenarios, and avoid blocking the OnExecute
code (which should not need to wait on the UI to display log messages). For example:
procedure TForm2.Log(const s: string);
begin
TThread.Queue(nil,
procedure
begin
mLog.Lines.Add(s);
end
);
end;
or:
uses
..., IdSync;
type
TLog = class(TIdNotify)
protected
FMsg: string;
procedure DoNotify; override;
public
constructor Create(const s: string); reintroduce;
end;
constructor TLog.Create(const s: string);
begin
inherited Create;
FMsg := s;
end;
procedure TLog.DoNotify;
begin
Form2.mLog.Lines.Add(FMsg);
end;
procedure TForm2.Log(const s: string);
begin
TLog.Create(s).Notify;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
I: Integer;
begin
BroadcastListenerIPv6.DefaultPort := 6000;
for I := 0 to BroadcastListenerIPv6.Bindings.Count - 1 do
BroadcastListenerIPv6.Bindings.Items[I].Port := BroadcastListenerIPv6.DefaultPort;
BroadcastListenerIPv6.MulticastGroup := 'FF02:0:0:0:0:0:0:1';
BroadcastListenerIPv6.Active := True;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
I: Integer;
begin
BroadcastServerIPv6.Port := 6000;
BroadcastServerIPv6.MulticastGroup := 'FF02:0:0:0:0:0:0:1';
BroadcastServerIPv6.Active := True;
BroadcastListenerIPv6.DefaultPort := 6000;
for I := 0 to BroadcastListenerIPv6.Bindings.Count - 1 do
BroadcastListenerIPv6.Bindings.Items[I].Port := BroadcastListenerIPv6.DefaultPort;
BroadcastListenerIPv6.MulticastGroup := 'FF02:0:0:0:0:0:0:1';
BroadcastListenerIPv6.Active := True;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
I: Integer;
LIP: string;
begin
FLocalAddresses := TIdStackLocalAddressList.Create;
GStack.GetLocalAddressList(FLocalAddresses);
for I := 0 to FLocalAddresses.Count - 1 do
begin
if FLocalAddresses[I].IPVersion = TIdIPVersion.Id_IPv6 then
begin
LIP := FLocalAddresses[I].IPAddress;
Break;
end;
end;
if LIP.IsEmpty then
Exit; // <======
BroadcastServerIPv6.Port := 6000;
BroadcastServerIPv6.MulticastGroup := 'FF02:0:0:0:0:0:0:1';
BroadcastServerIPv6.Active := True;
BroadcastListenerIPv6.DefaultPort := 6000;
for I := 0 to BroadcastListenerIPv6.Bindings.Count - 1 do
begin
BroadcastListenerIPv6.Bindings.Items[I].Port := BroadcastListenerIPv6.DefaultPort;
BroadcastListenerIPv6.Bindings.Items[I].IP := LIP;
end;
BroadcastListenerIPv6.MulticastGroup := 'FF02:0:0:0:0:0:0:1';
BroadcastListenerIPv6.Active := True;
end;
BroadcastListenerrIPv6.IPVersion := Id_IPv6
or BroadcastListenerIPv6.Bindings.Items[I].IPVersion := Id_IPv6
to match the IP you are assigning? Why do you have a Binding created at design-time if you are just going to overwrite it at runtime? You may as well just use Bindings.Add()
at runtime instead.
const
cMulticastGroupIPv6 = 'FF02:0:0:0:0:0:0:1';
procedure TForm1.FormCreate(Sender: TObject);
var
I: Integer;
LBinding: TIdSocketHandle;
begin
FLocalAddresses := TIdStackLocalAddressList.Create;
GStack.GetLocalAddressList(FLocalAddresses);
BroadcastServerIPv6.Port := 6000;
BroadcastServerIPv6.MulticastGroup := cMulticastGroupIPv6;
BroadcastServerIPv6.Active := True;
BroadcastListenerIPv6.DefaultPort := 6000;
BroadcastListenerIPv6.IPVersion := TIdIPVersion.Id_IPv6;
BroadcastListenerIPv6.MulticastGroup := cMulticastGroupIPv6;
BroadcastListenerIPv6.Bindings.Clear;
for I := 0 to FLocalAddresses.Count - 1 do
begin
if FLocalAddresses[I].IPVersion = TIdIPVersion.Id_IPv6 then
begin
LBinding := BroadcastListenerIPv6.Bindings.Add;
LBinding.IP := FLocalAddresses[I].IPAddress;
LBinding.IPVersion := TIdIPVersion.Id_IPv6;
LBinding.Port := BroadcastListenerIPv6.DefaultPort;
end;
end;
BroadcastListenerIPv6.Active := True;
end;