2009. 10. 1. 12:47

개발환경
- Visual Studio 2005 (SP1)
- Windows Vista Home Premium K (32-bit)




폼 디자인...
뭐 특별한건 없고 그냥 간단간단 설정좀 했습니다.
textBox1 만 있고 나머지는 그냥 배치만...

그림에 빠졌는데 반복횟수란 글자는 레이블(Label) 컨트롤 배치해 놓은것 입니다.


윗 부분에 쓰레드 사용을 위한 네임 스페이스를 지정해 줍니다.


Form1 클래스의 상단에 프로그램 전체에서 사용될 변수를 선언해 줍니다.
여기서는 쓰레드 3개를 사용하는 것으로 합니다.


Form을 더블클릭 하면 폼의 로드 이벤트로 넘어갑니다.
여기서 반복 횟수 입력 상자에 디폴트로 지정된 반복 횟수(th_Count)를 출력해 줍니다.

textBox1 에 실제로 내용을 출력해 주는 부분입니다.
쓰레드 내에서 이 함수에 값을 넘기면, textBox1에 내용을 추가하고 줄 바꿈 하는 형식으로 되어있습니다.

쓰레드가 반복횟수를 다 채우게 되면 하게 될 작업 입니다.

디자인 폼에서 button1 을 더블클릭 하면 button1의 클릭 이벤트로 넘어옵니다.
여기서 기본적인 셋팅과 함께 각 쓰레드들을 시작 시키는 일을 합니다.

- 현재의 반복횟수를 나타내는 변수 i 를 0으로 초기화 시킵니다.
- th_Count(반복횟수 지정)변수에 textBox2 에 입력된 숫자값을 입력합니다. (문자이면 ?)
- textBox1 을 클리어 시킵니다. (이전에 동작된 내용을 삭제)
- 쓰레드 동작중에 쓰레드 시작을 하게되는 button1 과 반복횟수 입력 되는 textBox2 를 건드리지 못하도록 Disable 시킵니다.

* textBox2 에 문자값이 들어가더라도 걱정할 이유는 없습니다.
소스코드에 보면 button1_Click 이벤트의 제일 첫 줄에 try 가 쓰이고 있습니다.
기본적인 형태는
try
{
//작업내용...
}
catch { }
입니다.

try 구문에 있는 작업 내용을 실행하되, 중간에 오류가 발생하면 그 시점에서 catch 구문으로 던져버립니다.
그런데 catch 에서 할 내용은 아무것도 없이 비워놓았으니 그냥 끝나버리게 됩니다.
만약 try catch 없이 그냥 본 내용이 들어갔을 경우, 문자값이 textBox2에 들어가면 뭔가 오류 메시지 박스가 뜨겠지요;;

경우에 따라서 try catch 에서 catch 구문에 친절하게 오류발생시 작업내용(오류 알림 상자... 등)을 작업하여도 됩니다.

쓰레드 th1, th2, th3 에서 수행할  AA(), BB(), CC() 입니다.
내용은 같습니다.
다만 출력할 때, 어느 쓰레드에서 작업한 내용인가를 알려주기 위한 문자값과, 쓰레드 시작 플래그 값만 조금 다를 뿐입니다.

- 일단 쓰레드가 시작되면 i의 값을 1 증가 시킵니다.
- 그리고 문자형 변수에 i의 값을 기록하고
- sPrint 함수에 현재 쓰레드를 알려줄 문자와 함께, 그 값을 던져 textBox1 에 출력 되게 합니다.
- i 의 값이 반복횟수 카운터(th_Count)의 값 이상이 되면 Reset_Ctrl() 함수를 호출하여 쓰레드를 중단 시킵니다.

폼이 종료 될때 해야 할 일을 기술하기 위해 Closing 이벤트를 생성해야 합니다.

폼 디자인 에서 폼을 선택한 후, 속성창에 보면 번개모양(이벤트) 아이콘이 있습니다.
여기서 FormClosing 부분을 찾은다음, 옆부분에 커서가 위치한 부분의 공란을 더블클릭 하여 줍니다.

그리하면, Form1 의 Closing 이벤트로 넘어옵니다.
여기서 할일은 쓰레드를 중단 하는것 입니다.

폼(Form1)이 종료될 때 쓰레드의 시작 플래그를 false 상태로 만들고, 쓰레드를 중단시킵니다.

컴파일 후, 실행하면 이렇게 나옵니다.
여러 개의 쓰레드가 동시에 동작을 하면서 sPrint()함수 에서 미처 줄바꿈을 실행하기도 전에 다른 쓰레드로 부터 값이 마구 들어와서 생기는 문제입니다.

다음과 같이 수정해 봅시다.
textBox1에 문자 기록하고 줄바꿈 하는 작업에 lock()을 씌워 봅시다.

그리고 다시 실행을 하면...
이제야 뭔가 형태를 갖춰서 실행이 됩니다.

lock() 을 걸게 되면 lock()이 풀릴때 까지 그 내부 코드에 다른 코드가 간섭을 못하게 잠금처리 해주는거 같아보이는 군요...

그런데... 순서가 좀 이상하죠? 숫자의 순서가 뒤죽박죽 입니다.
그럼 다른 부분에 잠금 처리를 하여 보겠습니다.

일단 sPrint 부분의 lock() 을 다시 제거 하여 줍니다.

변수 i 의 값을 증가 시키고 출력 시키는 부분에 lock()를 걸어 봅시다.
여기서는 AA() 의 수정된 코드만 표시합니다만, 실제로 BB()와 CC()도 이렇게 수정하여야 합니다.

변수 i의 값을 증가 시키고, 문자형으로 변환, 출력 하는 부분을 lock 으로 감싸서 도중에 다른코드로 부터 간섭을 받지 않도록 수정하였습니다.

이제 실행하게되면...
숫자가 정상적으로 순서대로 출력되는 것을 볼 수 있습니다.

숫자 앞의 쓰레드 문자는 랜덤 입니다.
실행 할때 마다 다른 쓰레드가 뜬다는거죠...

근데 한가지... 300 번 반복 시켰는데 302 ??

여기 올리지는 않았지만 쓰레드 1개를 제거하고 다시 돌리니 301 까지 뜨는것으로 봐서 쓰레드 3개 가 동시에 돌다가 중단 처리 하는 과정에 나머지 2개가 미처 실행중이던 내용을 기록하는게 아닌가 추측해 봅니다.



*** 위에서 AA(), BB(), CC() 부분은 내용이 거의 비슷비슷 합니다.
이것을 좀더 간단하게 만들어 봤습니다.
th_work() 함수를 작성하여 그것을 호출하였습니다.

실컷 다 만들어 놓고 다 써놓고 나서 생각나서 걍 생각나는대로 끄적여 봤습니다. ^^
저렇게 바꿔도 결과는 동일 합니다.

Posted by 해비