귀하는 손님 이십니다
로그인
회원가입
  
  델마당 공식 은행계좌
  하나은행 227-910235-83607
  예금주 이상국(운영진)
프로젝트 게시판
투표게시판
델마당소개
기초부터 활용까지! 델파이 교육 - 데브기어
 광고문의 :
강좌, 팁, 정보 강좌, 팁, 정보 입니다.
글내용 - 강좌, 팁, 정보
 익명함수+쓰레드를 활용한 간단한 쓰레드 사용 방법
클라우
(조대현)
2018-03-03 오후 10:08:15
카테고리: 팁
2259회 조회



등록된 파일이 없습니다.
기존에는 TThread를 상속하여 구현하였기에 초보시절엔 접근도 어렵고 잠깐 쓰레드가 필요한 시점에서의 활용도 번거로웠습니다.
다행히 델파이 2010버전부터 익명함수가 제공되었는데 덕분에 쓰레드를 아주 손쉽게 사용할 수 있습니다.
다만, 여기서는 자세히 설명할 순 없지만 안전한 쓰레드 사용을 위해 크기 2가지를 지켜야 합니다.

1) 쓰레드의 begin ~ end 블록 사이에서 UI를 조작(변경, 수정, 삭제등)할때는 Syncronize를 이용한다.
2) 다른 쓰레드와 동시에 같은 자원(변수, 클래스등)을 공유(동시에 읽거나 쓰는 행위, 포인터를 참조하는 행위)하지 않는다.

간단한 예제입니다.

1. 100ms 타이머 만들기

델파이 기본 타이머는 윈도우 이벤트 방식으로 구현되므로 다음과 같은 치명적인 단점이 있습니다.

1) 정확도가 떨어지고(윈도우 컨디션에 따라 100~500ms 이하 작동 불규칙)
2) 메인UI(메인쓰레드)가 멈추지 않고 작업 불가능

그래서 필수로 쓰레드를 이용한 타이머를 사용하게 됩니다.
익명함수를 사용하면 아래와 같이 손쉽게 만들 수 있습니다.

procedure TForm1.FormCreate(Sender: TObject);
begin
    TThread.CreateAnonymousThread(procedure
    begin
      while Applicaton.Terminated do
      begin
        Sleep(100);
        DoTimerTick; // DoTimerTick에서 소요되는 시간을 모두 기다리므로 while문을 통해 중복 실행되지는 않습니다.
      end;
    end).Start;
end;

procedure TForm1.DoTimerTick1;
var
  i, k: integer;
begin
  // 여기서부터 백그라운드 작업을 하면 됩니다.
  // 메인 UI를 멈추게 하지 않습니다.

  // 이런 for 구문도 아주 빠르게 동작하며 메인UI도 정상적으로 작동합니다.
  for i ;= 0 to 9999999999 do
  begin
    Inc(k);
  end;

  // sleep도 메인UI가 정상적으로 작동합니다.
  sleep(1000);

  // 메인 UI를 조작하려면 Synchronize 처리합니다.
  TThread.Synchronize (TThread.CurrentThread, procedure ()
  begin
    Label1.Caption := IntToStr(k);
  end);
  
  ShowLogMsg('타이머 작동 중...');
end;

procedure TForm1.ShowLogMsg(AMsg: String);
begin
  // 최초 호출 시점이 쓰레드라면 아래와 같이 Synchronize 처리
  TThread.Synchronize (TThread.CurrentThread, procedure ()
  begin  
    Memo1.Lines.Add(AMsg);
  end);
end;


2. 버튼 클릭 시 대기시간 구현

procedure TForm1.Button1Click(Sender: TObject);
begin
  Label1.Caption := '파일 복사 시작';

  TThread.CreateAnonymousThread(procedure
  begin
    FileCopy('c:\org.avi', 'd:\dst.avi'); // 용량 100mb avi 파일 복사 

    TThread.Synchronize (TThread.CurrentThread, procedure ()
    begin  
      Label1.Caption := '파일 복사 종료';
    end);
  end).Start;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  TThread.CreateAnonymousThread(procedure
  begin
    TThread.Synchronize (TThread.CurrentThread, procedure ()
    begin  
      Edit1.ReadOnly := true;
      Edit1.Caption := '2초 후 입력 가능';
    end);
    
    Sleep(2000);
 
    TThread.Synchronize (TThread.CurrentThread, procedure ()
    begin  
      Edit1.ReadOnly := false;
      Edit1.Caption := '이제부터 입력 가능';
    end);    
  end).Start;
end;