Reputation: 18171
I'm using TIDTCPServer component. As I understood event ServerTCPExecute(AContext: TIdContext)
is not synchronized. What is the best way of synchronising it? I need data to be send to main thread and have them back to format answer.
I'm using Indy 10.5.8.0.
Method 1
Is it something like this I should deal with critical sections to pass data from non synchronized function to application?
var data:string;
.
.
.
procedure MainThreadProcedure;
begin
...
end;
.
.
.
procedure IdTCPServerExecute(AContext: TIDContext);
var tmp: string;
begin
.
.
.
EnterCriticalSection(cs);
data:= tmp;
TIdYarnOfThread(AContext.Yarn).Thread.Synchronize(MainThreadProcedure);
LeaveCriticalSection(cs);
end;
Upvotes: 5
Views: 5181
Reputation: 596557
The correct way is to use Indy's TIdSync
class instead of accessing Indy's internal threads directly, eg:
uses
..., IdSync;
type
TMySync = class(TIdSync)
protected
procedure DoSynchronize; override;
public
data: string;
end;
procedure TMySync.DoSynchronize;
begin
// this runs in the main thread
// use data as needed...
end;
procedure IdTCPServerExecute(AContext: TIDContext);
var
tmp: string;
sync: TMySync;
begin
tmp := ...;
sync := TMySync.Create;
try
sync.data := tmp;
sync.Synchronize;
finally
Sync.Free;
end;
end;
Just be careful with any synchronizing you do, whether it be TIdSync
or TThread.Synchronize()
. If the main thread tries to deactivate the server while the server is trying to sync with the main thread, you will deadlock both the main thread and the server.
Upvotes: 12
Reputation: 4776
In my application, I'm using this code:
procedure MainThreadProcedure;
begin
...
end;
.
.
.
procedure IdTCPServerExecute(AContext: TIDContext);
begin
TIdYarnOfThread(AContext.Yarn).Thread.Synchronize(MainThreadProcedure);
end;
Be sure to use a critical section or other synchronization object if you need to access main thread variables in ServerTCPExecute
Upvotes: 0