waz*_*123 -3 delphi multithreading mutex
cs.Acquire;
try
AContext.Connection.Socket.Write(packet);
finally
cs.Release;
end;
Run Code Online (Sandbox Code Playgroud)
要么
EnterCriticalSection(cs);
AContext.Connection.Socket.Write(packet);
LeaveCriticalSection(cs);
Run Code Online (Sandbox Code Playgroud)
我试图在线程中将我的数据包发送到服务器,但我有20个线程,它也将数据发送到同一个连接套接字.我尝试使用Critical Section或Mutex,它们都不起作用,我收到所有线程发送时的垃圾.
这都是关于我之前的问题
数据包看起来像这样:
LengthData
0000000010HelloWorld
服务器接收数据:
ReadBytes(10);
len := (Then remove zeros from begining);
ReadBytes(len); // data.
Run Code Online (Sandbox Code Playgroud)
有时我会在ReadBytes(10)中收到垃圾,它是长度+数据的混合,例如:"10Hellowor"
如果我只使用一个线程将数据发送到服务器,那么每次都可以正常工作.如果发送了很多线程,那么一切都会出错.
如果使用得当,CS /互斥锁可以正常工作.确保您的线程锁定相同的 CS/mutex实例,而不是单独的实例.由于您是从服务器端发送数据,我建议使用该OnConnect事件创建每个连接的CS并将其存储在TIdContext.Data属性中,并将OnDisconnect事件释放到该属性中,例如:
procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
begin
AContext.Data := TCriticalSection.Create;
end;
procedure TForm1.IdTCPServer1Disconnect(AContext: TIdContext);
begin
AContext.Data.Free;
AContext.Data := nil;
end;
Run Code Online (Sandbox Code Playgroud)
然后你可以在需要时这样做:
TCriticalSection(AContext.Data).Acquire;
try
AContext.Connection.Socket.Write(packet);
finally
TCriticalSection(AContext.Data).Release;
end;
Run Code Online (Sandbox Code Playgroud)
稍微更封装的用法是从中派生出一个新类TIdServerContext,例如:
type
TMyContext = class(TIdServerContext)
private
CS: TCriticalSection;
public
constructor Create(AConnection: TIdTCPConnection; AYarn: TIdYarn; AList: TThreadList = nil); override;
destructor Destroy; override;
procedure SendPacket(const AData: TIdBytes); // or whatever parameters you need
end;
constructor TMyContext.Create(AConnection: TIdTCPConnection; AYarn: TIdYarn; AList: TThreadList = nil);
begin
inherited;
CS := TCriticalSection.Create;
end;
destructor TMyContext.Destroy;
begin
CS.Free;
inherited;
end;
procedure TMyContext.SendPacket(const AData: TIdBytes);
begin
CS.Acquire;
try
Connection.IOHandler.Write(AData);
finally
CS.Release;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
IdTCPServer1.ContextClass := TMyContext;
end;
Run Code Online (Sandbox Code Playgroud)
然后你可以在需要时这样做:
TMyContext(AContext).SendPacket(packet);
Run Code Online (Sandbox Code Playgroud)