Delphi에서 라인을 어떻게 끝내는지 (이 라인은 정해진 시간에 실행됩니다) (방안 1)

5664 단어 Delphi
스레드 대상이 풀리기 전에 먼저 스레드가 실행 중인지 확인해야 합니다. 만약 스레드가 실행 중이 아니라면 (스레드 ID가 0이 아니고 스레드 종료 표시가 설정되지 않았음) Terminate 프로세스를 호출해서 스레드를 종료합니다.Terminate 프로세스는 다음 코드와 같이 스레드 클래스의 Terminated 플래그를 간단하게 설정합니다.
procedure TThread.Terminate;

begin

    FTerminated:= True;

end;


따라서 스레드는 즉시 스레드를 종료하는 것이 아니라 정상적으로 끝난 후에도 계속 실행해야 한다. 이 점에 주의해야 한다.
여기서 주제 밖의 말을 합니다. 어떻게 해야 '즉시' 라인을 종료할 수 있습니까? (현재는 TThread로 만든 라인을 가리킵니다.)결과는 당연히 안 되지!스레드를 종료하는 유일한 방법은 Execute 방법이 실행되는 것입니다. 따라서 일반적으로 스레드를 빨리 종료하려면 Execute 방법에서 비교적 짧은 시간 안에 Terminated 로고를 계속 검사해서 제때에 종료할 수 있도록 해야 합니다.이것은 라인 코드를 설계하는 매우 중요한 원칙이다!
물론 만약에 당신이 반드시'즉시'라인을 종료할 수 있다면 TThread 클래스는 좋은 선택이 아니다. API로 라인을 강제로 종료하면 최종적으로 TThread 라인의 대상이 정확하게 방출되지 않고 대상을 분석할 때Access Vilation이 나타날 수 있기 때문이다.이 경우 API 또는 RTL 함수로만 스레드를 만들 수 있습니다.
 
예를 들어 다음과 같은 예: 정해진 시간에 실행되는 라인을 어떻게 끝내는가
위의 빨간 글자에서 언급한 원칙과 같이, 비교적 짧은 시간 안에 Terminated 로고를 계속 검사해서 제때에 퇴출할 수 있도록 해야 한다.
procedure TDoSomeThingThread.Execute;

var

  i: Integer;

begin

  inherited;

  CanFree := False;

  try

    while not Self.Terminated do

    begin

      ........

      {

                             ,

                        ,

                           Terminated  

           True     ,

                        Terminated  ,        

      }

      ........

      Sleep(5);

      Application.ProcessMessages;

    end;

  finally

    CanFree := True;

    {               ……    }

  end;

end;


 
이 안에 있는CanFree는 TDoSomeThingThread의 속성입니다. (대응: private FCanFree: Boolean;) 
CanFree는 TDoSomeThingThread 라인이 언제 풀릴 수 있는지 표시하기 위해서입니다.
상황 1: Terminated가 True인지 확인하면 정해진 시간에 실행되는 순환에서 벗어나finally에서 CanFree를 True로 설정합니다
상황2:try에서 이상이 발생하면 정해진 시간에 실행되는 순환이 튀어나오고finally에서 CanFree를True로 설정합니다
다음은 TDoSomeThingThread를 끝내고 방출하는 함수를 소개합니다
procedure DestroyAThread(testThread: TDoSomeThingThread); stdcall;

var

  itime: Cardinal;

begin

  if Assigned(testThread) then

  begin

    testThread.Terminate;      //    testThread  Terminated     True

    itime := GetTickCount;     //getTickCount。                  ,   :  

    while GetTickCount - itime < 10000 do

    begin

      Sleep(1);    //Sleep()            

      if testThread.CanFree then

      begin

        Break;

      end;

    end;

    testThread.Free();

  end;

end;




여기에 있는 코드 (스레드의 Execute 및 함수Destory Athread)
1) testThread 실행 중
바로 Execute의 코드를 실행하고 있는 것입니다. 이때 Execute에서Terminated의 값을 검사합니다. Fasle이기 때문에 첫 번째while 순환에 들어갈 수 있습니다. for 순환에 들어가서 Terminated가 False인지 검사할 수 있습니다. 그래서 계속 실행합니다.
2)DestroyAthread(testThread) 호출;
우선testThread가Assigned인지 확인하고, 만약 그렇다면testThread를 사용하십시오.Terminate; Terminated 속성을 True로 설정하고 테스트 Thread를 기다리는 Execute에 들어가서 Terminated가 True로 설정되었는지 확인하십시오
그 중의 순환 코드 세그먼트
while GetTickCount - itime < 10000 do

begin

  Sleep(1);

  if testThread.CanFree then

  begin

    Break;

  end;

end;


10밀리 초 동안 1초가 지나면testThread의CanFree 값을 검사하고 True라면 Break에서 순환을 벗어나십시오
왜 10밀리초일까요? Execute에 5밀리초마다 순환적으로 실행되기 때문에 여기에 설정된 시간이 5초보다 길면 CanFree 검사 값을 놓치지 않을 수 있습니다. (사실 10밀리초도 CanFree 검사 값을 놓치지 않을 수 없습니다)
또한 위의 Execute 코드에서는 다음과 같이 설명합니다.
          while  (    )             ,

                           Terminated  

           True     ,

                        Terminated  ,        

예컨대
procedure TDoSomeThingThread.Execute;

var

  i: Integer;

begin

  inherited;

  CanFree := False;

  try

    while not Self.Terminated do

    begin

      for i:=0 to 1000 do

      begin

         if Self.Terminated then

            break;

         {

                     

         }

      end;

      Sleep(5);

      Application.ProcessMessages;

    end;

  finally

    CanFree := True;

    {               ……    }

  end;

end;


내부의 순환에서Terminated의 값을 순환적으로 검사해야 하는 이유는 바로 제때에 종료할 수 있도록 하기 위해서이다. 순환할 때마다 검사하지 않으면 이런 상황이 발생할 수 있기 때문이다.DestroyAthread에서Terminated를True로 설정했지만 이때 대기 라인의Execute에서 마침 검사를 실시했기 때문이다(그래서 검사된Terminated는False이기 때문에 계속 실행한다).이때 그의 작업 코드에 들어가면 큰 순환이 된다면 13밀리초, 10밀리초를 초과하면 문제가 발생한다. 라인이Terminated를 True로 검사하고 CanFree를 True로 설정할 때 10밀리초가 지났기 때문에DestroyAthread에서 CanFree를 검사하지 못했기 때문에 라인 제어, 라인이 종료되면 문제가 발생한다.
그래서 이것을 통해 왜 Execute 방법에서 비교적 짧은 시간 안에 Terminated 로고를 끊임없이 검사해야 제때에 퇴출할 수 있는지 이해할 수 있다.
이 비교적 짧은 시간에 어떻게 설정하고 어떻게 제어하는지는 다중 루틴 프로그래밍의 중요한 기교이다!한편, Execute에서 어떻게 비교적 짧은 시간 안에Terminated의 값을 검사할 수 있는지를 고려하고,DestroyAthread와 같은 끝 라인의 함수에 라인의 피드백을 기다리는 시간을 얼마나 설정해야 하는지도 고려해야 한다.
상기 예에서 말한 바와 같이 정시 순환에 추가된 층(또는 여러 층 순환)이 있고 모든 순환이 순환하기 전에Terminated의 값을 검사했다. 가입은 True가 검사되지 않았을 때(아래 코드가 계속 실행될 때) 마침 DestroyAthread 함수가Terminated를True로 설정했다.그리고 10밀리초의 대기 라인을 순환하여Terminated의 값을 검사하여 자신의 임무를 끝내고 자원을 방출하며 CanFree 표지를 True 알림 DestroyAthread로 설정합니다. 그러나 문제가 발생했습니다. 라인의 이번 순환은 자물쇠가 사라지거나 자원을 기다리거나 다른 원인으로 인해 10밀리초(20밀리초)를 넘게 실행했고 20밀리초 후에야 Terminated의 값을 검사한 다음에 임무를 끝내고 자원을 방출할 때근데 DestroyAthread는 10밀리초가 넘게 기다렸으니까그래서 여기도 고민거리가 생겼다.
  ??이 문제를 어떻게 해결할 것인가
3) TestThread의 Execute 메서드에 추가
Terminated 속성이 True로 설정되어 있는지 확인하면 정해진 시간에 실행되는 순환을 벗어나 작업을 끝냅니다. 만약 라인이 많은 자원을 신청한다면, 이때도 신청한 자원을 방출하고, CanFree를 True로 설정하고, 다른 사람이 종료할 수 있는지 확인하고, Free를 떨어뜨릴 때까지 기다립니다.
4)DestroyAthread(testThread) 다시 보기;안쪽
CanFree가 테스트 Thread의 Execute 방법에 의해 True로 설정되었는지 순환적으로 검사합니다. (테스트 Thread는 이미 자신의 Execute 방법에서 실행된 작업을 끝내고 방출될 수 있음을 알려주는 함수입니다.) 그리고 테스트 Thread입니다.Free;라인 풀기
주의:Destroy () 를 직접 호출하지 말고, 더 안전한 Free () 방법을 호출하십시오. Free () 는 이 대상의 실례가 NIL이 아니라는 것을 확인하고, 대상의 분석 방법인Destroy () 를 호출하는 것을 우선적으로 선택하기 때문입니다.

좋은 웹페이지 즐겨찾기