델파이에서 스레드를 사용하는 다양한 방법을 보여줍니다

너무 많은 델파이 사용자가 스레드가 응용 프로그램의 성능을 향상시키는 일종의 마술이라고 생각하는 실수를합니다. 불행히도, 이것은 사실이 아닙니다. 스레드를 구현하려고 할 때 가장 큰 실수는 응용 프로그램의 시각적 컨트롤에 직접 액세스하는 것입니다. 그러나 이러한 시각적 제어는 응용 프로그램의 기본 스레드의 맥락에서만 작동 할 수 있습니다. 다른 스레드를 사용하여 사용자 인터페이스에서 컨트롤을 업데이트하는 것은 매우 신중하게 계획하고 구현해야합니다. 그리고 대부분의 경우 문제에 대한 올바른 해결책이 아닐 수도 있습니다.
간단히 말해서, 델파이의 VCL 프레임 워크는 스레드 안전하지 않습니다. 스레드를 UI에 통합하는 방법에는 여러 가지가 있지만 단일 단일 크기의 솔루션은 없습니다. 항상 달성하려는 것에 따라 다릅니다. 대부분의 경우 사람들은 더 나은 성능 (속도)을 달성하기를 원합니다. 그러나 그것은 스레드를 사용하여 거의 수행되지 않습니다. 대신 스레드가 사용자 인터페이스에 통합되는 가장 일반적인 시나리오는 긴 작업 중에 해당 UI를 응답하는 것입니다.
이를 위해 클릭하면 인터넷에서 파일을 다운로드하는 단일 버튼 만있는 간단한 응용 프로그램을 상상할 수 있습니다. 응용 프로그램에는 이미 전체 UI에 사용되는 하나의 기본 스레드가 있습니다. Windows 플랫폼에서 이것은 Windows 메시지를 보내거나 수신하고 제어 캔버스로 그리기, 사용자 상호 작용 인식 등을 의미합니다.이 스레드는 본질적으로 매우 빠르게 회전하는 거대한 루프입니다. 이 회전 스레드의 모든 혁명에 대해 특정 코드가 실행됩니다.
단일 스레드 환경 에서이 파일 다운로드는 다운로드가 완료 될 때 까지이 루프가 회전에서 차단됩니다. 이 기간 동안이 스레드는 더 이상 UI 업데이트, 사용자 클릭을 감지 할 수 없습니다. 이것은 Windows가 그러한 형태의 제목에 넣지 않게하는 이유입니다.
여기에는 추가 스레드가 들어오는 곳입니다. Windows에 응답해야합니다. 이 거대한 파일 다운로드로 기본 UI 스레드를 차단하는 대신 해당 파일을 다른 스레드에 넣을 수 있습니다. 단순히 단순 해요?
"진행 상황을 어떻게 모니터링합니까?" 또는 "완료되면 어떻게 알 수 있습니까?" 이것은 다운로드 스레드가 어떻게 든 기본 스레드와 상호 작용해야한다는 것을 의미합니다. 이것은 혼란이 나오는 곳입니다. 한 스레드는 다른 스레드를 방해 할 수 없습니다. 하나의 스레드가 실제로 어떤 지점에 있는지는 알 수 없기 때문에 다른 스레드를 방해 할 수 없습니다. 현재 두 개의 별도 루프가 있으며 UI를 업데이트하려면 UI 스레드가 어디서나 일할 수 있습니다. 가장 중요한 것은 메인 UI 스레드가 다른 스레드가 쓰기를 원하는 동일한 제어 속성에 문자열을 작성하는 과정에 있다고 가정합니다. 이제 두 개의 스레드가 동일한 메모리 주소에 쓰려고 시도하여 예측할 수없는 문제가 발생할 수 있습니다.
동기화하여. Delphi의 tthread 클래스에는 메소드 Synchronize ()가있어 실제로 그러한 발생을 기대할 때 실제로 제대로 작동하는 순간에만 스레드가 기본 UI 스레드와 상호 작용할 수 있습니다. 다른 스레드에서 동기화 된 코드는 실제로 해당 스레드의 맥락에서 실행되지 않습니다. 항상 기본 UI 스레드의 맥락에서 실행됩니다. 이것이 Synchronize ()의 아이디어는 UI 스레드에서 코드를 실행하는 것입니다.
결국, 당신은 실제로 스레드에서 VCL을 사용하지 않습니다. 대신, 스레드는 기본 스레드에 신호를 보내고 기본 스레드가 준비된 경우에만 해당 코드를 실행합니다. 한편, 2 차 스레드가 차단되는 동안 메인 스레드가 끝날 때까지 차단됩니다.
그런 다음 스레드에서 큰 UI 작업이 더 나을 것이라고 생각하는 실수가 있습니다. 수백만 개의 항목을 채우고 싶은 목록이 있다고 가정 해 봅시다. 물론 시간이 걸리고이 기간 동안 응용 프로그램은 응답하지 않을 것입니다. 다시. 그래서 그 코드를 스레드로 옮기십시오.
다시, 모든 UI 상호 작용은 기본 스레드와 기본 스레드에서만 수행해야합니다. 스레드는 긴 계산을 수행하고, 대량의 데이터를 처리하거나, 원격 자원의 응답을 기다리거나, 시간이 많이 걸리고 UI와 직접 관련이없는 것들이 있으면 유용합니다.
말하기 어렵습니다. 그러나 스레드를 작성할 때 고도로 권장되는 일반적인 관행이 있습니다. 스레드 코드를 자체 단위에 넣으십시오. 이 장치는 다른 UI 장치에서 분리해야합니다. 사용 조항에 VCL 관련 단위조차 없어야합니다. 스레드는 그것이 어떻게 사용되고 있는지조차 알지 못해야합니다. 긴 작업을 수행 할 목적으로 본질적으로 더미 여야합니다. 스레드의 UI 업데이트와 관련하여 동기화 된 이벤트에서 가장 잘 수행됩니다.
정확히 어떻게 생각하는지. 앞에서 설명한대로 동기화 된 이벤트입니다. 이벤트는 단순히 스레드가 시작되기 전에 할당 할 수있는 절차에 대한 포인터입니다. 스레드 내부에서 UI를 업데이트해야 할 때 Synchronize ()를 사용 하여이 이벤트를 트리거합니다. 이 디자인을 통해 스레드는 UI가 사용하고 있음을 알 필요가 없습니다. 동시에, 당신은 또한 우연히 추상화를 달성합니다. 스레드가 재사용됩니다. 사용자 인터페이스가없는 다른 프로젝트에 연결할 수 있습니다 (Windows 서비스라고 가정 해 봅시다).
검색하고 싶지 않은 경우 VCL 스레드 안전에 대한 관련 리소스에 대한 직접 링크가 있습니다 ...
이 응용 프로그램은 델파이의 스레드 사용을 보여줍니다. 알아야 할 많은 것들이 있기 때문에 다른 목적을 위해 다른 섹션으로 나뉩니다. 각 주제에는 최소 1 개의 양식 단위 (탭 시트에 포함됨)와 사용자 인터페이스를 제외하고는 기능을 포함하는 최소 1 개의 독립형 단위가 있습니다. 이것은 스레드가 모든 UI에서 분리 되어야 함 을 보여주기 위해 의도적으로 수행됩니다.
주요 형태 자체에는 실제로 논리가 없습니다. 그것이하는 모든 일은 양식을 탭에 포함시키는 것입니다. FormCreate() 이벤트 핸들러에서 각 탭 시트에 대한 양식을 인스턴스화하는 수많은 호출을 EmbedForm() 로 만듭니다.
실제로 응용 프로그램을 사용하는 것은 매우 간단합니다. 당신은 단지 탭 중 하나로 이동하면 각각 자체 지침이 있습니다.


인터넷에서 스레드에서 파일을 다운로드하는 방법을 보여줍니다. 다운로드를 수행하는 단일 범용 기능 정의 DownloadFile() 있습니다. UI에는 3 개의 버튼이 있습니다.
기본적으로 다운로드 할 URL은 ThinkBroadband.com에서 제공하는 테스트 파일이지만 원하는 URL을 사용할 수 있습니다. 파일을 저장할 위치를 선택할 수도 있습니다. 이것은 매우 간단한 데모이므로 로컬 파일 이름의 파일 이름/확장을 요구 사항에 맞게 조정해야합니다. 다운로드하는 URL의 자동으로 변경되지는 않습니다 (일반적으로 브라우저와 같이).

긴 작업을 수행하는 스레드에서 진행률 표시 줄을 업데이트하는 방법을 보여줍니다.

스레드 내에서 데이터베이스 연결을 사용하고 데이터를 UI 스레드와 동기화하는 것을 보여줍니다.

프로세서를 테스트하기 위해 대규모 CPU 사이클을 소비하는 여러 스레드를 보여줍니다.