我正在通過Indy套接字處理流式數據包字符串,並且在客戶端,我有一個線程,它從TIdTCPClient
中讀取傳入數據並不斷將此數據附加到單個字符串緩衝區的末尾。我有另一個線程,它從頭開始連續讀取此緩衝區,根據需要複製(和刪除)數據(一次完成一個完整的數據包)。從兩個線程保護字符串緩衝區?
我知道在任何情況下,訪問相同變量的兩個線程都可能是危險的。但這是否也適用於字符串?或者只是對象?我能從兩個不同的線程讀取/寫入相同的字符串,感覺安全嗎?如果不是,那麼我應該怎麼做才能保護這個字符串?這是一個簡單的字符串,稱爲FBuffer
。
我將數據追加到最後,像這樣:
procedure TListenThread.CheckForData;
begin
if FClientSocket.Connected then begin
FClientSocket.IOHandler.CheckForDataOnSource(5000);
if not FClientSocket.IOHandler.InputBufferIsEmpty then
FBuffer:= FBuffer + FClientSocket.IOHandler.InputBufferAsString;
end;
end;
而另一個線程正在讀它,像這樣:
procedeure TPacketThread.CheckForPacket;
var
P: Integer; //Deliminator position
T: String; //Temp copying string
Z: Integer; //Expected packet size
begin
P:= Pos('#', FBuffer);
if P > 0 then begin //Is the deliminator found?
T:= Copy(FBuffer, 1, P-1); //Copy up to deliminator...
Z:= StrToIntDef(T, 0); //Convert packet size to integer...
if Z > 0 then begin
//Is there a full packet waiting in buffer?
if Length(FBuffer) >= Z then begin
//First, delete size definition and deliminator...
Delete(FBuffer, 1, P);
//Now grab the rest of it up to the packet size...
T:= Copy(FBuffer, 1, Z);
//Delete what we just copied...
Delete(FBuffer, 1, Z);
//Finally, pass this packet string for further processing...
ProcessPacket(T);
end;
end;
end;
end;
的代碼是我的代碼的簡化版本,只是展示我需要做的所有工作FBuffer
。
FBuffer是一個常規的'string'嗎? –
@WarrenP是的,只是一個普通的字符串。 –
將數據加載到某個Tbuffer對象並將其排隊到生產者 - 消費者隊列上的處理線程更爲常見。只要您關閉一個Tbuffer實例,請創建一個新實例。這完全避免了與共享字符串相關的大量繁瑣,雜亂的代碼等,並且消除了對新數據的極度浪費的輪詢。這一點,並消除虛假分享。 –