C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[2578] Re:TThread내에서 VCL객체의 사용과 TThread의 종료
박지훈.임프 [cbuilder] 6022 읽음    1999-12-26 00:00
:  String temp;
:     TListItem *li = Form1->ListView1->Items->Add () ;
:     temp = Filename;
:     li->Caption = temp;
:     li->ImageIndex =  FileInfo.iIcon;
:
:     temp = Size;
:     li->SubItems->Add (temp);
:
:     temp = Pathname;
:     li->SubItems->Add (temp);
:
: 위의 코드가 아이템을 삽입하는 부분입니다...전혀 문제 될게 없습니다...
: 지우는 부분은 ListView->Items->Clear를 호출하구요...역시 전혀 문제 될게 없습니다...
:
:
: 몇날 몇일 테스트를 해본 결과...
: 리스트에 item을 삽입하는 Thread의 문제 인 것 같습니다...
:
: 제 프로그램의 로직은 item의 삽입은 dirThread에서 하게 되고...
: Item을 모두 지워야 하는 경우에는 main에서 clear를 호출합니다...
: dirThread는 수십개 정도가 생성되는데, 이 dirThread들이 정상 종료를 하면...
: clear를 불러도 에러가 되지 않는 걸로 결론을 내렸습니다...
: 문제는 돌고 dirThread들을 죽이고, clear를 호출하는 건데...
:
: while(1)
: {
:    .....
:    dirThread->Suspend();
:    dirThread->Terminate();
:    delete dirThread;
:    if ( dirThread ) ShowMessage("alive");
:     ....GetNextThread()...
:    if (xxx) break;
: }
: listView->Items->Clear();
:
: 이런 과정을 거치게 되는데....
: 죽였던 모든 Thread에서...살아있다고 alive이라는 메시지가 뜹니다...-_-;;;
: 책에서 "Thread의 강제 종료"라는 항목이 있어서 읽어봤는데....
: Thread를 자신이 아닌 Thread가 자신을 죽이면 바로 죽지 않는다는군요...음...
: 그리고 C++빌더 헬프를 봐도 Terminate를 호출하면 바로 죽는게 아니라...어쩌구..
: 그래서 그런 건지...
:
: 여하튼...Thread가 죽지 않기 때문인 것 같습니다...
: 그리고...Item을 삽입하는 코드는 세마포로 단 하나의 Thread만이 집입하게 해놔서...
: Thread를 전부다 죽이고 Clear()를 호출했을 때,
: 그 단 하나의 Thread가 Item을 삽입하는 코드에 영향을 미치면...에러가 나는 거고...
: 그 이후나...그 전이라면 에러가 나지 않는 거 같습니다...
: 그래서...불규칙적인 에러가 나는 것 같습니다...
: 음...이럴 경우...어떻게 해결을 해야하는지 생각을 골똘히 해봤는데...
:
: 일단...돌고 있는 Thread가 정상종료할때 까지 기다릴 수 없는 경우가 있기 때문에...
: 참...까다롭습니다...그래서 생각한 것이...
: ListView->Clear하지 않고, Clear가 된 ListView가 필요한 놈에게는 다른 ListView를 동적으로
: 생성해서 주는 겁니다...그리고 이전의 ListView는 이전의 dirThread들을 강제 종료 시키고...
: 적당한 시간 뒤에...clear를 하는 겁니다...그리고 이 2개의 ListView를 번갈아 가면서
: 사용하는 겁니다...음...더블 버퍼링 같은거라고 할 수 있을지...음...
:
: 그런데..TListView를 어떻게 동적생성을 하죠??? 그 많은 프로퍼티를 설정해야 합니까???
: 아니면...속성을 카피해 온다던가...뭐 그런거 없나요??? 일단 시도를 해봤는데...
: 잘 안되네요...
:
: 그런데 이 방법도 문제가 있습니다...사용자가 그냥 종료를 눌러버리면...-_-;;;
: 음...괜찮은 해결책 없을까요???
:
: 가장 좋은 해결택은 Thread를 즉각 강제 종료시키는 것인데...
: 음...
:



임펠리테리입니다.

저번엔, 쓰레드를 사용한다는 말씀은 하지 않으셨었죠? 쓰레드를 사용한다면 다른 고려해야 할
사항들이 많이 있습니다. 먼저, 리스트뷰의 아이템을 추가하는 등의 VCL 그래픽 객체를 사용하는
작업을 디폴트가 아닌 쓰레드에서 하려면, 반드시 Syncronize() 메소드를 사용해야 합니다.
기본적으로 VCL의 대부분의 클래스는 thread-safe하지 않기 때문에, VCL 객체에 접근하는 코드가
있다면 그 코드만 별도로 떼어내어서 TThread 클래스 내에 별도로 인자와 리턴값을 가지지 않는
함수로 만들고 Syncronize() 함수를 사용해서 호출해야 합니다. 이 방법에 대해서는 TThread 객체
를 새로 생성하면 빌더가 주석처리된 예제를 통해 보여주고 있으니 참고하시구요.

또 한가지.
TThread는 Terminate()가 호출되어도 즉각 종료되지 않습니다. TThread 내부의 Execute() 함수가
종료되어야 실제로 TThread가 종료됩니다. (TThread의 실행루틴이 Execute() 함수인 것은
아시겠죠?) Terminate() 함수가 하는 일은 단지 Terminated 프로퍼티를 true로 세팅하는 것 뿐
입니다. 그래서 Exeucte() 함수내에서 무한루프를 돌면서 Terminated 프로퍼티를 검사하도록
코딩하는 것이 보통입니다. 또한 무한루프를 돌고 있다고 하더라도, 루프내에서 입력대기함수에서
실행이 블라킹되어 있는 경우라면 Terminated를 검사할 기회가 전혀 없으므로 종료되지 않습니다.
void __fastcall qqq::Execute()
{
    while(!Terminated)
        ... // 반복해서 해야 할 일들
}

또, Execute()가 종료되더라도 디폴트로는 TThread가 파괴되지 않습니다. 종료즉시 파괴되도록
하려면, FreeOnTerminate 프로퍼티를 true로 세팅해주어야 합니다.

그럼 참고하시길...

+ -

관련 글 리스트
2569 [질문] TListView->Item->Clear() 에러는... 신정호 4056 1999/12/24
2578     Re:TThread내에서 VCL객체의 사용과 TThread의 종료 박지훈.임프 6022 1999/12/26
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.