2014-11-26 2 views
-2

나는 실을 가지고 있습니다. 그 안에는 UDP 패킷을 보내는 루프가 있습니다. 이 루프에서 다음 메시지를 보내기 전에 장치의 UDP 응답을 기다려야합니다 (이전 패킷을받은 경우 [OK 또는하지 않음]). 오류가 나는 스레드를 중지하는 경우 확인을 StringList의 다음 메시지를 보냅니다. 그것을 만드는 방법? 그리고 나는 더 필요합니다 : 소프트웨어가 장치의 응답을받지 못하면 3 초의 타임 아웃을 구현해야합니다.멀티 스레드 - 타임 아웃을 만드는 방법과 "인터 로킹"을 만드는 방법은 무엇입니까?

저는 TIdUDPServer를 사용하여 udp 패키지를 수신합니다.

TEnvioFirmware = class(TThread) 
    private 
    I: integer; 
    Lock: TCriticalSection; 
    mMac: string; 
    mVersao: integer; 
    mProduto: integer; 
    _max: integer; 
    _min: integer; 
    mIP: string; 
    firmware_string: TStringList; 
    idpclnt: TIdUDPClient; 
    progress: TProgressBar; 
    lbPorc: TLabel; 
    bAck: Boolean; 
    procedure Executar; 
    procedure OnVerificarTimeOut(Sender: TObject); 
    public 
    tmrTimeout: TTimer; 
    bContinua: Boolean; 
    procedure Execute; override; 
    constructor Create(CreateSuspended: Boolean; firmware_string: TStringList; 
     edtIP: string; idpclnt: TIdUDPClient; max, atual: integer; 
     var pb: TProgressBar; var lblPorcentagem: TLabel; abAck: Boolean); 

    end; 

procedure TEnvioFirmware.Execute; 
begin 
    inherited; 
    // Synchronize(Executar); 
    Executar; 
end; 

procedure TEnvioFirmware.Executar; 
var 
    I, J: integer; 
    X: pacote; 
    Y: String; 
    B: String; 
    B2: String; 
    msgCount: integer; 
    Buffer: TBytes; 
    // array[0..5] of Byte; 
    max, atual: integer; 
    BufferSend: TBytes; 
begin 

    SetLength(Buffer, 6); 

    idpclnt.Host := mIP; 
    idpclnt.Active := true; 
    msgCount := firmware_string.Count; 
    max := msgCount - 1; // Progress Bar 
    // pb.Max := max; 
    self.progress.Min := 0; 
    self.progress.max := max; 

    B := '12345'; 
    B2 := '0'; 

    if bAck then 
    begin   //trying to make timeout 
    tmrTimeout := TTimer.Create(nil); 
    tmrTimeout.Interval := 3000; 
    tmrTimeout.OnTimer := OnVerificarTimeOut; 
    end; 

    bContinua := True; 


    for I := 0 to msgCount - 1 do 
    begin 

    B[1] := chr(15); 
    B[2] := chr(0); 
    B[3] := chr(2); 
    B[4] := chr((I) mod 256); 
    B[5] := chr((I) div 256); 

    B2[1] := chr(255); 

    Y := B + firmware_string.Strings[I] + B2; 

    SetLength(BufferSend, Length(Y)); 

    for J := 0 to Length(BufferSend) - 1 do 
    begin 

     BufferSend[J] := Ord(Y[J + 1]); 

    end; 



    if bContinua then 
     idpclnt.SendBuffer(BufferSend); //after send the device will response 

    if not bAck then 
    begin 
     Sleep(200); 
     bContinua := true; 
     progress.Position := I + 1; 
     lbPorc.Caption := 
     IntToStr(Round((100 * progress.Position)/progress.max)); 
     atual := I; 
    end 
    else 
    begin 

     tmrTimeout.Enabled := True; 

    end; 

    end; 

    Buffer[0] := $0F; 
    Buffer[1] := 00; 
    Buffer[2] := 03; 
    Buffer[3] := (msgCount) mod 256; 
    Buffer[4] := (msgCount) div 256; 
    Buffer[5] := 255; 

    idpclnt.SendBuffer(Buffer); 

    Sleep(150); 

end; 

UDPRead에 당신이 당신의 패킷을 직렬화 할 필요가 있기 때문에, 스레드의 TIdUDPServer 외부를 사용하는 대신 스레드 내부 TIdUDPClient를 사용해야합니다

if (AData[0] = 15) and (AData[1] = 1) and (AData[2] = 2) and (Count = 5) 
    then 
    begin 

    if AData[3] = 0 then 
    begin 
     MainEstrutura.objFirmwareUpdater.bContinua := true; 
     MainEstrutura.objFirmwareUpdater.tmrTimeout.Enabled := false; 
    end 
    else 
    begin 
     MainEstrutura.objFirmwareUpdater.bContinua := false; 
     MainEstrutura.objFirmwareUpdater.tmrTimeout.Enabled := false; 
    end; 

    end; 
+1

"많이 했어요"라는 말은 게시물에 적어도 하나 이상 포함시켜야한다는 의미입니다. 추가 하시겠습니까? –

+0

게시했습니다. 충분하다? –

+0

스레드의 UI 컨트롤은 무엇입니까? 그게 어떻게 작동 할 수 있는지는 알 수 없습니다. –

답변

2

: 여기

내 코드입니다 . 그런 다음 OnUDPRead 이벤트를 동기화하거나 타이머를 사용하지 않아도됩니다. 간단히 스레드 SendBuffer()을 보내는 패킷이 있고 즉시 ReceiveBuffer() 시간 제한이 지정된 인바운드 응답을 지정하고 완료 될 때까지 필요에 따라 루핑을 계속합니다. 제한 시간이 경과하면 필요에 따라 아웃 바운드 패킷을 다시 보내거나 스레드를 종료하십시오.

이 상황에서 TIdUDPServer을 사용하는 유일한 이유는 여러 펌웨어 스레드가 동시에 실행되고 모두 동일한 IP/포트에 응답하는 경우입니다.이 경우 단일 TIdUDPServer을 수신하는 것이 좋습니다 모든 응답을 필요에 따라 각 적절한 펌웨어 스레드로 전송합니다.

관련 문제