우리는 INDY를 사용하는 Delphi 클라이언트 서버 응용 프로그램을 가지고 있습니다. 클라이언트는 다중 스레드 된 서버에 대한 단일 tIdTCPClient 연결을가집니다. 클라이언트는 "이론적으로"단일 스레드입니다. 그러나 실제로는 클라이언트에 여러 스레드가 있고 이것은 내 문제가있는 곳입니다. 예를 들어 매분마다 서버에서 데이터를 가져 오는 타이머를 생각해보십시오. 그리고 사용자가이 타이머 이벤트와 동시에 명령을 실행할 때 어떤 일이 일어나는지 고려하십시오. 사실, 내 문제는 (귀찮게) 보고서의 모든 페이지를로드하는 데 시간이 걸리는 "보고서 작성기"보고 도구로 인해 발생합니다. 이 보고서는 한 번에 여러 레코드를 전송하는 캐싱 메커니즘이있는 "특수"데이터 세트에서 실행됩니다 (따라서 모든 데이터를 얻기 위해 서버를 여러 번 호출합니다). 동시에 사용자가 다른 작업을 수행하면 교차 데이터가 표시되는 것 같습니다. 사용자가 보고서 용 데이터를 되 찾는 것 같습니다.타이머 이벤트 및 기타 멀티 스레드 클라이언트 측 이벤트가있는 Delphi tIdTCPClient
그러나이 버그는 매우 드뭅니다. 그러나 세계에서 가장 느린 인터넷을 가진 특정 고객에게는이 버그가별로 드물지 않습니다. (행운을 빌어 이제 테스트 환경이 있습니다.)
그래서 클라이언트에 나는 코드를 가지고 같은 비트 ... 나는 그것을 디버깅 할 때이 절차의 중간에 두 개의 스레드가있을 때
procedure DoCommand(MyIdTCPClient:tIdTCPClient; var DATA:tMemoryStream);
var
Buffer: TBytes;
DataSize: Integer;
CommsVerTest: String;
begin
//Write Data
MyIdTCPClient.IOHandler.Write(DATA.Size);
MyIdTCPClient.IOHandler.Write(RawToBytes(Data.Memory^,DataSize));
//Read back 6 bytes CommsVerTest should always be the same (ie ABC123)
SetLength(Buffer,0); //Clear out buffer
MyIdTCPClient.IOHandler.ReadBytes(Buffer,6);
CommsVerTest:=BytesToString(Buffer);
if CommsVerTest<>'ABC123' then
raise exception.create('Invalid Comms'); //It bugs out here in rare cases
//Get Result Data Back from Server
DataSize:=MyIdTCPClient.IOHandler.ReadLongInt;
Data.SetSize(DataSize); //Report thread is stuck here
MyIdTCPClient.IOHandler.ReadBytes(Buffer,DataSize);
end;
지금, 내가 버그를 확인할 수 있습니다. 예외시 주 스레드가 중지됩니다. 그리고 보고서 스레드는 동일한 절차의 다른 어딘가에 붙어 있습니다.
그래서, 스레드 안전 위의 절차를 만들어야 할 것처럼 보입니다. 나는 사용자가 무언가를 원할 경우보고 스레드가 끝날 때까지 기다려야한다는 것을 의미합니다.
Arrrgh, 제 클라이언트 응용 프로그램이 서버로 데이터를 보내는 단일 스레드라고 생각했습니다!
보고서 작성기 내부의 스레드에 액세스 할 수 없어 TThread를 사용하면 작동하지 않는다고 생각합니다. 나는 tCriticalSection이 필요하다고 생각합니다.
위의 절차를 한 번에 하나의 스레드에서만 실행할 수 있도록 응용 프로그램을 만들어야한다고 생각합니다. 다른 스레드는 기다려야합니다.
누군가가 구문을 사용하십시오.