|
: 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로 세팅해주어야 합니다.
그럼 참고하시길...
|