델파이

Delphi Thread 정리

지병철 2023. 8. 1. 17:26

uThreadTest.fmx
0.00MB
uThreadTest.pas
0.01MB

Delphi 에서 사용되는 Thread 를 정리한다.

본 문서에서 사용하는 코드는 Delphi Alexandria 버전의 FMX 환경에서 제작되었다.

 

Delphi Thread 의 구성은 아래와 같다.

  1. TThread
    • Synchronize
    • Queue
    • CreateAnonymousThread
  2. TTask
  3. TParell
  4. TMonitor

Thread 는 멀티스레딩을 구현하는 기능이며, 여러작업을 동시에 처리하거나 비동기 처리를 할 수 있게 해 준다.

> 백그라운드 작업 (TTask, TThread.CreateAnonymousThread)

> 병렬처리 (TTask, TParallel.For)

> 동기화 (TThread.Synchronize, TThread.Queue)

Thread를 사용할 때 주의할 점은 사용자 인터페이스(UI), 즉 화면을 제어하는 Main Thread 와의 충돌을 피해야 한다는 것이다.

화면을 변경할 필요가 있을 때에는 TThread.Syncronize() 를 이용하여야 한다.

(TThread.Queue 를 사용할 수도 있으나, Syncronize 와는 동작하는 방식이 차이가 있다. 아래에 이 부분에 대하여 설명을 첨부하였다)

Thread 는 특히 비동기식으로 코드가 실행되는, Android 나 iOS 앱을 만들 때 매우 유용하다. UI 를 담당하는 Main Thread 를 사용하여 입출력 연산, 느린 작업을 진행하면, 화면이 정지되어 보이기 때문에, Thread 를 이용하여 이를 피할 수 있다. (특히, Callback 함수가 사용될 때, 전달 받은 응답 값에 따라, 무엇인가 변경을 하려 하면, 화면이 정지되어 보일 때가 많다.)

 

> 동기화: Synchronize 와 Queue 의 차이점

Synchronize 와 Queue 는 Main Thread 를 사용한다는 공통점이 있으나, 동시에 여러개를 연속으로 사용할 경우, Synchronize는 동기식으로 실행되나, Queue 는 Main Thread 의 메시지 큐에 추가(비동기식)되어, Main Thread 가 처리할 때 실행이 됩니다.

아래 Synchronize 의 경우 Main Thread 가 동기식으로 실행되어, memo1 에 1, 2 가 순서대로 출력된다.

아래 TThread.Queue 의 경우 Main Thread 의 큐에 추가되어 비동기식으로 실행되기 때문에, memo1 에는 2, 2 가 출력된다. Main Thread 실행 시, 큐에 추가된 Thread.Queue 부분이 처리되는데, 처리전에 이미 두 군데의 cnt := cnt + 1; 부분은 실행되어 있기 때문이다. 

아래와 같이 Synchronize 와 Queue 를 동시에 사용할 경우 memo1 에 어떠한 숫자가 표시될 지는 알 수 없다. 두 개의 CreateAnonymousThread 는 비동기식으로 작동하기 때문이다.(보통은 Queue 부분의 cnt := cnt + 1; 부분이 먼저 실행되어 memo1 에는 3, 3, 4, 4 혹은 3, 4, 4, 4 가 찍힐 것이다.)

Synchronize 를 먼저 실행시키고 싶다면, 두번째 CreateAnonymousThread 부분에 sleep() 함수를 사용하여 delay 를 주면 된다.(memo1 에 출력되는 순서는 1, 2, 4, 4 이다)

 

Thread 의 실행순서

Thread 의 실행은 '생성 > 실행 메서드 > 스레드 생성 및 시작 > 스레드 동기화 > 스레드 종료' 순으로  진행되는데, Delphi 에서 자동 처리해 주는 부분들도 있어서, 생략해 줄 수 있는 부분도 있다.

 

Thread 의 종료시점

Tread 는 실행이 완료되는 시점에서 종료된다.

Thread 종료 시점을 조절하려면, 변수를 사용하여야 하며, 수동으로 메모리에서 Free 시켜야 한다.

ThreadSuspendeResume

Thread 를 계속 실행하면서, Thread 의 실행을 멈추었다 다시 실행하려면, suspend 와 resume 을 이용하면 된다.

TMonitor 사용

TMoniter 를 사용하는 이유는, 멀티스레드 환경에서 동기화를 제공하기 위해서 이다. 멀티스레드 환경에서는 일반적으로 비동기 작업이 이루어지는데, 가끔 멀티스레드 환경에 동기화 작업이 필요한 경우가 발생한다.

멀티스레드 환경에서 데이터를 요청하고, 수신 받은 결과값을 이용하여 특정한 일을 하는 코드를 만들어 실행하려면, 결과값이 도착할 때 까지 기다리도록 할 필요가 있다. TMonitor 를 이용하면 기다리게 할 수 있다.

 

아래는 btnTMonitor 버튼을 클릭한 후 키보드를 누르면, 그 값을 화면에 보여주려고 하는 코드이나, Thread.CreateAnonymouseThread 는 그대로 실행되고 끝난다.

TMonitor를 이용하여 위의 코드를 완성해 보면 다음과 같다.

위 기능을 구현하기 위해서, Thread 안에 sleep() 함수를 사용할 수 있지만, sleep 함수는 Android, iOS 환경에서는 동작하지 않으며, Windows 환경에서 사용할 경우 sleep 함수에서 지정한 시간동안 무조건 기다려야 한다는 단점이 존재한다.

 

- 이상 -

'델파이' 카테고리의 다른 글

Delphi iOS 제작 시 Datasnap.DSConnect 문제 발생 및 해결  (0) 2023.08.01