|
좋은 지적 감사드립니다.
자동 생성되는 소스의 주석을 세심히 살펴보겠습니다.
^^
evergreen 님이 쓰신 글 :
: 헉! Thread 처리부(Execute())에서 VCL 객체를 동기화(Synchronize())없이
: 마구잡이로 사용하시는 군요. 동기화 없이 VCL를 사용하면 VCL이 화냅니다(정말입니다). -_-b
: File --> New --> Thread Object
: 하면 생성되는 Unit File의 SRC에 보면
: Important: 쏼라 쏼라
: 부분을 조금 더 신중히 보시고 작성중인 프로그램를 수정하시기 바랍니다.
: - heredity -
:
:
: 냉큼이 님이 쓰신 글 :
: : 안녕하세요. 언제나 눈팅만 하는 아직은 허접초짜입니다.
: :
: : 한개의 파일을 여러개의 USB에 복사시켜주는 프로그램을 만들고 있습니다.
: : 그런데 테스트로 3개의 USB에 파일을 복사하는 테스트를 하다가
: : 어느 한 USB에만 많은 시간이 할당되는 경우가 나타나서 질문하게 되었습니다.
: :
: : 참고적으로, 스레드 클래스 안에서 메인폼의 리스트뷰를 갱신하고
: : 스레드 클래스 안에서 프로그래스바를 생성했다가 소멸하는 루틴이 있기는 합니다만
: : 이것이 어느 한쪽으로만 몰리는 이유가 될까요?
: :
: : 아니면, 한개의 파일을 여러군데에서 오픈하여 사용하기 때문에
: : 이런 현상이 나타나는 걸까요?
: :
: : 이 현상을 해결하고자 고민하다가 예전에 배웠던 자바에서
: : 각 스레드들에게 시간(?)을 균등하게 분배해주는 무엇이 있었다는 생각이 어렴풋이 들었습니다.
: : 혹시 C++에도 그런게 있지 않을까 해서요.
: :
: : 아래는 현재의 소스 일부입니다.
: :
: : [main.cpp]
: : -----------------------------------------------------------------------------------
: : #include "ThreadUpGrade.h"
: :
: : ThreadUpGrade *UpThread[16];
: : unsigned char DriveBuffer[26];
: :
: : __fastcall TFormMain::TFormMain(TComponent* Owner)
: : : TForm(Owner)
: : {
: : int i;
: :
: : for (i = 0; i < 16; i++)
: : {
: : // 초기화
: : UpThread[i] = NULL;
: : }
: : }
: :
: : void __fastcall TFormMain::BitBtnCopyClick(TObject *Sender)
: : {
: : int i;
: :
: : for (i = 0; i < GetConnectCount(); i++)
: : {
: : UpThread[i] = new ThreadUpGrade(true);
: : UpThread[i]->ThdID = i;
: : UpThread[i]->ThdDrive = DriveBuffer[i]; // 연결된 USB의 드라이브 문자 배열
: : UpThread[i]->ThdActive = true;
: : UpThread[i]->ThdListView = ListViewStat; // 스레드에서 메인폼의 리스트뷰를 컨트롤하기 위하여
: : UpThread[i]->Resume();
: : }
: : }
: : -----------------------------------------------------------------------------------
: :
: : [ThreadUpGrade.cpp]
: : -----------------------------------------------------------------------------------
: : void __fastcall ThreadUpGrade::Execute()
: : {
: : //---- Place thread code here ----
: : TestFileCopy();
: : }
: :
: : void ThreadUpGrade::TestFileCopy(void)
: : {
: : AnsiString source, target;
: :
: : source = "C:\\Test\\Test.DAT";
: : target = (AnsiString)ThdDrive + ":\\Test.DAT";
: : FileCopying(source, target, "Test.DAT");
: : }
: :
: : bool ThreadUpGrade::FileCopying(AnsiString SourcePath, AnsiString TargetPath, AnsiString msg)
: : {
: : HANDLE hRead, hWrite;
: : char buf[BUF_SIZE];
: : DWORD dwret;
: : int file_size, result;
: : TRect rect;
: :
: : TListItem *tmpList;
: : tmpList = ThdListView->Items->Item[ThdID];
: :
: : TProgressBar *pProgressBar = new TProgressBar(this);
: : pProgressBar->Parent = ThdListView;
: :
: : // 소스파일을 얻어온다
: : hRead = CreateFile(SourcePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL);
: : if (hRead == INVALID_HANDLE_VALUE)
: : {
: : // ThdListView->Items->BeginUpdate();
: : tmpList->SubItems->Strings[2] = "소스 파일을 찾을 수 없습니다.";
: : // ThdListView->Items->EndUpdate();
: : delete pProgressBar;
: : CloseHandle(hWrite);
: : return false;
: : }
: :
: : // 대상파일을 얻어온다
: : hWrite = CreateFile(TargetPath.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL);
: : if (hWrite == INVALID_HANDLE_VALUE)
: : {
: : // ThdListView->Items->BeginUpdate();
: : tmpList->SubItems->Strings[2] = "대상 파일을 만들 수 없습니다.";
: : // ThdListView->Items->EndUpdate();
: : delete pProgressBar;
: : CloseHandle(hRead);
: : CloseHandle(hWrite);
: : return false;
: : }
: :
: : // 메인폼의 리스트뷰 안에 프로그래스바를 표시하기 위함
: : rect = ThdListView->Items->Item[ThdID]->DisplayRect(drBounds);
: : pProgressBar->Top = rect.Top + BAR_PADDING;
: : pProgressBar->Left = rect.Left + ThdListView->Columns->Items[1]->Width + ThdListView->Columns->Items[0]->Width;
: : pProgressBar->Width = ThdListView->Columns->Items[2]->Width;
: : pProgressBar->Height = rect.Height();
: :
: : pProgressBar->Min = 0;
: : pProgressBar->Max = GetFileSize(hRead, NULL);
: : pProgressBar->Position = 0;
: :
: : // 메세지를 작성한다
: : // ThdListView->Items->BeginUpdate();
: : tmpList->SubItems->Strings[2] = msg + " 파일을 복사중 입니다";
: : // ThdListView->Items->EndUpdate();
: :
: : // 파일을 복사한다
: : while (true)
: : {
: : memset(&buf, 0x00, BUF_SIZE);
: : ReadFile(hRead, &buf, BUF_SIZE, &dwret, NULL);
: : pProgressBar->Position += dwret;
: :
: : if (dwret == BUF_SIZE)
: : WriteFile(hWrite, &buf, BUF_SIZE, &dwret, NULL);
: : else if (dwret > 0)
: : WriteFile(hWrite, &buf, dwret, &dwret, NULL);
: : else
: : break;
: : }
: :
: : result = pProgressBar->Max - pProgressBar->Position;
: : delete pProgressBar;
: : CloseHandle(hRead);
: : CloseHandle(hWrite);
: :
: : // 종료 메세지
: : if ( !result )
: : {
: : // ThdListView->Items->BeginUpdate();
: : tmpList->SubItems->Strings[1] = "복사 완료";
: : tmpList->SubItems->Strings[2] = msg + " 파일을 복사하였습니다.";
: : // ThdListView->Items->EndUpdate();
: : return true;
: : }
: : else
: : {
: : // ThdListView->Items->BeginUpdate();
: : tmpList->SubItems->Strings[1] = "복사 실패";
: : tmpList->SubItems->Strings[2] = msg + " 파일 복사가 중단되었습니다.";
: : // ThdListView->Items->EndUpdate();
: : return false;
: : }
: :
: : return false;
: : }
: : -----------------------------------------------------------------------------------
: :
: : [ThreadUpGrade.h]
: : -----------------------------------------------------------------------------------
: : class ThreadUpGrade : public TThread
: : {
: : private:
: :
: : protected:
: : void __fastcall Execute();
: :
: : public:
: : char ThdID;
: : char ThdDrive;
: : bool ThdActive;
: : TListView *ThdListView;
: :
: : void TestFileCopy(void);
: : bool FileCopying(AnsiString SourcePath, AnsiString TargetPath, AnsiString msg);
: :
: : __fastcall ThreadUpGrade(bool CreateSuspended);
: : };
: : -----------------------------------------------------------------------------------
|