외규장각 도서 환수 모금 캠페인

Search Results for '쓰레드'

3 POSTS

  1. 2007.08.09 Working Thread 2
  2. 2007.06.01 Thread 해결 ^____________________^ 2
  3. 2007.06.01 쓰레드 ㅠ_ㅡ 2

Working Thread

Posted 2007. 8. 9. 18:04, Filed under: Study/Computer Science

오늘 열심히 툴을 만들다가 또 쓰레드 때메 지난 번이랑 똑같은 문제로 고생하는 거도 피곤하고-
하나밖에 못넘겨주는 파라미터로 다이얼로그를 넘겨도 UpdateData도 안되고 여기저기 걸리는게 많아서 고생ㅠ
(지난번에 고생해서 알아냈다시피 쓰레드 내에서는 윈도우(UI쪽)를 건드리지 않는 것이 상책이다.)
그래서 이승희 주임님한테 물어봤다 -_-  (창환이 말로는 Windows UI 프로그래밍 쪽으로 일가견이 있으시다고)


[문제점]

UI와 내부 연산을 분리할 것
UI 관련 부분 (윈도우로부터 데이터를 받아오거나 출력하거나, 윈도우 상태를 변경하는 부분) 들이 쓰레드 안에 들어가서 파일을 옮기고 프로세스를 실행하는 등의 실제 연산 중간중간에 박혀있다.
작업 쓰레드 내에서 UI 관련 연산을 하는 건 안좋은 습관.

초기화를 비롯한 실행 조건 처리는 첫부분에서 한꺼번에 할 것
파일을 복사할 경로를 확인하고 파일 복사, V3 경로 확인하고 실행.
이런 식으로 그 때 그 때 확인하는 것보다는 실행하는데 필요한 모든 조건을 확인한 후에 작업을 시작하도록.

예외처리
이 코드에서는 안나타나지만 파일 이동에 대해서 예외처리를 제대로 해주지 않았다.
어떤 이유에서든 연산이 실패할 가능성이 있으면 예외처리 루틴으로 가도록-

------------------

사실 저 모든게 쓰레드를 제대로 사용할 줄 몰라서 그런거다 -_-
저 연산들이 순차적으로 실행되어야하는 연산이기 때문에 WaitForSingleObject 를 써서 기다려야되는데
Thread의 경우는 WaitForSingleObject의 파라메터로 CThread 포인터를 바로 넘기는게 아니라
CThread->m_hThread를 넘겨줘야 한단다.

전에 한번 WaitForSingleObject 써봤는데 쓰레드만 생성하고 바로 돌아와서 메인쓰레드랑 동시에 실행되는 바람에 순차적 실행이 안됐던 적이 있었는데 핸들값을 잘못 넘겨줬기 때문이었나보다.

여튼 그래서 순차적으로 실행되도록 하려고 쓰레드에 다 밀어넣고 했는데 이러면 안된다고 하시는군.
Cleaner.MoveSample(), V3.Run(), Cleaner.RemoveEmptyFolder() 만 각각 쓰레드를 생성하여 실행하는 것이
좋다고 한다.


Working Thread와 UI Thread를 분리해야한다는 말은 많이 들었지만 어떻게 해야하는지
잘 몰랐는데 대충 이렇게 하는건가;;
조금 깔끔해 진것 같긴 하지만 어설프다. 그래도 그럭저럭 필요한 기능은 전부 구현이 되서 만족 ^^
한가지 아쉬운거라면 저 쓰레드 함수들.. Dialog 밑에 주렁주렁 달려있어서 좀 이상하다는거.
좀 더 깔끔하게 정리된 코드를 짜고 싶다.
디자인 패턴을 공부해야지!

--------------------
굉장히 부끄러운 일이지만 회사에서 코딩을 하다보면 정직원분들이 상식이라고 생각하는 부분을 나는 잘 모르고 있는 경우가 많아서 정직원들이 내 코드를 보면 왜 이런식으로 짰을까- 라고 놀람을 떠나 어이없어하는 경우가 있다 -_- (변수명이라거나 예외처리라거나 하는 기본적인 부분부터 프로그램의 구조같은 것까지 여러가지 면에서)

정말이지 코딩같은건 어디서 체계적으로 배우는게 아니라서 (공이라고 해도 뭔가 체계를 가지고 배운 적은 없다. 이상한 일이긴 하지만) 참 힘들다. 지식도 지식이지만 코딩 습관 또한 중요한 부분을 차지하는 듯하다.





Response : ,

Thread 해결 ^____________________^

Posted 2007. 6. 1. 13:08, Filed under: Study/Computer Science

어제부터 고민하던 문제 완죤 해결 ㅋㅋㅋ

OK 버튼 눌렀을 때 실행하는 모든 프로시저를 스레드로 만들면 순차실행하는 데 아무런 문제 없음
전에 이런 방식으로 할려다가 Dialog Item 들을 마음대로 사용할 수 없어서 포기했는데 (5번 문제점)

CWnd를 상속한 클래스에서 멤버 함수로 핸들을 가지고 있으니까 이걸 써두 되고..
The m_hWnd data member is a public variable of type HWND

윈도우를 통째로 스레드 프로시저의 파라미터로 넘겨서 캐스팅하면 OnOK 함수 내에서 처럼 사용 가능하다는 것 ^^ .. 다른 맴버 변수에 직접 접근할 수 있기 때문에 이 방법이 더 깔끔하다.

스레드 첨 써봐서 진짜 힘들었는데.. 그럭저럭 인제 어째 되는지는 알겠다.
이번 경우는 스레드간 통신도 없고 동기화도 안해도 되는 별로 어렵지 않은.. 단지 스레드였지만
다음에는 더 어려운거에 도전해봐야지 ㅋㄷ

UINT threadCnt(LPVOID DlgHpcnt)
{
 // create class instances
 CHpCntDlg* Cntdlg = (CHpCntDlg*)DlgHpcnt;   // 이렇게 캐스팅해서 맘껏 사용 ㅋㄷ
 HpCounter* hpc = new HpCounter(Cntdlg);
 
 // disable button
 Cntdlg->GetDlgItem(IDOK)->EnableWindow(false);

 // Homepage upload count
 hpc->MakeTmp();   // make temporary folder
 Cntdlg->GetDlgItem(IDC_STEP)->SetWindowText("홈페이지 업로드 카운트 중...");

 if(Cntdlg->m_CheckINI ==TRUE) {
  hpc->WriteINICnt();
 }

 // Sample Count
 Cntdlg->GetDlgItem(IDC_STEP)->SetWindowText("엔진 샘플 수 카운트 중...");
 SpCounter* spc = new SpCounter(Cntdlg);
 for(int i = 0; i < 7; i++)
 {
  spc->TotalSample();
  spc->ECSample();
  spc->MoveDate();
 }
 
 CTimeSpan day = CTimeSpan(1,0,0,0);
 CTime Date = CTime::GetCurrentTime() - day;

 CString szBuffer = _T("");
 char szBuf[80] = _T("");


 
 // Print Result
 Cntdlg->m_Result.DeleteAllItems();
 Cntdlg->GetDlgItem(IDC_STEP)->SetWindowText("결과 출력");
 for (i = 0; i < 7; i++){
  szBuffer.Format("%8d.%02d.%2d", Date.GetYear(), Date.GetMonth(), Date.GetDay());
  Cntdlg->m_Result.InsertItem(LVIF_TEXT, 0, szBuffer, 0, 0, 0, 0);
 
   itoa((spc->arResult[6-i]).nTotalSample, szBuf, 10);
   Cntdlg->m_Result.SetItemText(0, 1, szBuf);

   
   itoa((spc->arResult[6-i]).nECSample, szBuf, 10);
   Cntdlg->m_Result.SetItemText(0, 2, szBuf);

   
   
   itoa((hpc->arResult[6-i]).nKorCnt, szBuf, 10);
   Cntdlg->m_Result.SetItemText(0, 3, szBuf);
   
   itoa((hpc->arResult[6-i]).nEngCnt, szBuf, 10);
   Cntdlg->m_Result.SetItemText(0, 4, szBuf);
   
  Date -= day;

 }
 //enable Run button
 Cntdlg->GetDlgItem(IDOK)->EnableWindow(true);
 
 return 0;
}

Response : ,

쓰레드 ㅠ_ㅡ

Posted 2007. 6. 1. 11:58, Filed under: Study/Computer Science

void CHpCntDlg::OnOK() {
 
UpdateData(TRUE);
HpCounter* hpc = new HpCounter(dlg);
 
 // Homepage upload count
 hpc->MakeTmp();   // make temporary folder
 GetDlgItem(hWnd ,IDC_STEP)->SetWindowText("홈페이지 업로드 카운트 중...");

 pHpthread = AfxBeginThread(threadHompageCnt, hpc);

 if( m_CheckINI == TRUE){
  hpc->WriteINICnt();
 }

 // Sample Count
 GetDlgItem(IDC_STEP)->SetWindowText("엔진 샘플 수 카운트 중...");
 SpCounter* spc = new SpCounter(this);
 pSptread = AfxBeginThread(threadSampleCnt, spc);
 pSptread->SuspendThread();

...

}

------

1. Ok 버튼을 눌렀을 때 수행되는 위의 프로시져가 웹페이지를 다운로드해서 파싱하고 결과를
   출력하는 시간이 꽤 걸리는 작업이라서 창을 다시 그려줄  때 깨지거나 응답없음이 나타난다.

2. 쓰레드를 이용해서 내부 프로시져가 돌아가는 거랑 창을 그려주는 걸 별도로 수행하도록 하면
    해결할 수 있음.

3. 쓰레드를 생성하기 위해서는 UINT 함수이름(LPVOID pParam); 와 같은 형식의 쓰레드에서
   실행하는 처리를 당담하는 프로시저가 필요함
   (형식의 제한이 있어서 복잡한 파라미터를 넘겨주는 함수를 구현할 수가 없었다.
    이럴 때는 파라미터를 모두 가지는 구조체를 선언하여 그 포인터를 넘기면 된다고 한다.)

4.  쓰레드를 생성할 때는 CreateThread 윈도우 API 보다는 AfxBeginThread를 사용하는 것이 바람직
C/C++의 표준 라이브러리를 사용하는 경우 프로세스 내의 스레드는 메모리 공간을 공유하기 때문에 정적 변수 사용등에 있어서 문제가 발생한다. (예: strtok) 이를 방지하기 위해서 윈도우에서 쓰레드마다 다른 메모리 영역을 정적으로 할당(TLS: Thread Local Storage) 이 때 TLS를 사용하기 위해서는 쓰레드를 생성할 때 초기화 등의 준비가 필요한데 CreateThread를 사용해 쓰레드를 생성하면 이런 처리를 할 수 없다.

5. 쓰레드 함수 내에서는 GetDlgItem() 함수를 호출할 수 없음. (쓰레드 함수는 전역으로 선언되어있고 윈도우(다이얼로그) 내부의 함수가 아니므로) 그리하여 GetDlgItem 부분은 OnOK() 함수에서 처리하고 나머지를 둘로 나누어 각각 쓰레드로 처리하려고 했는데.. 그렇게 했더니 파일 I/O 가 있는 부분에서 대기하는 동안 제어가 다른 쓰레드로 넘어가면서 병렬로 처리되고 결과가 제대로 안나온다. 순차적으로 처리해야하는 프로시저에서 분리를 목적으로 쓰레드를 사용하니까 참 맘대로 안된다.

6. 그래서 WaitForSingleObject() 를 사용해서 쓰레드 처리를 기다리려고 했는데. AfxBeginThread 함수나 CreateThread 함수는 쓰레드 생성에 성공하면 쓰레드 프로시저의 종료를 기다리지 않고 즉시 호출로부터 복귀한다. 그래서 WaitForSingleObject 가 별로 소용이 없다. 게다가 메인 프로시저는 쓰레드 프로시저의 상태와 상관없이 계속해서 프로그램을 실행하므로 출력루틴이 먼저 실행되는 사태가 발생해서 완전 결과가 엉망이 됐다.

7. 윈도우 자체를 쓰레드 프로시저에 넘겨주고 GetDlgItem를 호출할 수 있도록 만들려고 했는데 윈도우 핸들을 얻어오는게 맘처럼 쉽지가 않다 ;;

8. 쓰레드 핸들을 사용해서 한번 컨트롤 해봐야겠다..

쓰레드 너무 힘들다 ㅠ_ㅠ

Response : ,


Recent Posts

Recent Comments

Recent Trackbacks

Total hit (Today , Yesterday )

Admin Write Post