소년포비의 세계정복!!

[Thread] Thread 메서드에 매개변수 넘기기 본문

프로그램 세상/C#

[Thread] Thread 메서드에 매개변수 넘기기

소년포비 2009. 10. 6. 06:20

닷넷에서 Thread 를 생성하기 위해서는 ThreadStart 델리게이트를 이용해야 한다.
다음과 같이
Thread t = new Thread(ThreadStart(쓰레드메서드));
t.Start();
 
이렇게 하면 '쓰레드 메서드' 는 주 스레드와 분리된 다른 스레드(Worker Thread) 상에서 실행됨으로
비동기 처리가 가능하다.
 
그런데 이 ThreadStart 델리게이트는 다음과 같이 선언되어 있다.
public delegate void ThreadStart();
 
매개변수를 받을수 없을 뿐더라 반환값 역시 없다.
따라서 쓰레드 메서드는 매개변수를 가질 수 없다는 제약사항이 있다.
그러나 상황에 따라서 쓰레드 메서드에도 변수값 참조가 필요하다.
이때 쓰는 방법이 흔히 전역변수 나 클래스 변수를 가지고 적적히 사용하게 될 것이다.
 
이번 시간에는 쓰레드 메서드에 매개변수를 받을 수 있도록 하는 기법(?)에 대해 알아 본다.
핵심은 사용자 정의 델리게이트를 선언하여 비동기로 델리게이트를 실행하는 것이다.
 
우선 샘플 화면을 보자

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
GO 버턴을 누르면 주 쓰레드와는 다른 쓰레드에서 비동기로 처리가 시작된다.
쓰레드 메서드가 받아 들이는 매개변수는 터보 기능이라 하여 속도를 2배 올려주는 역할을 하는 매개변수이다
 
코드를 보자.
 

delegate void RunDelegate(int speed);

 

private void button1_Click(object sender, System.EventArgs e)

{                                                           

        int turbo = 2; //전달할 파라메타

        RunDelegate runDelegate = new RunDelegate(this.RunThread);

        runDelegate.BeginInvoke(turbo,null,null);           

}

              

#region Worker Thread 상에서 수행될 메서드(쓰레드 메서드임에도 매개변수를 가진다)

private void RunThread(int turbo)

{             

        for(int speed = 0; speed <= 100000; speed++)

        {

this.textBox1.Text += String.Format("속도 : {0} 으로 달리고 있습니다\r\n",speed*turbo );

        }

}

#endregion

 

쓰레드 메서드는 RunThread 이다.
이 메서드는 turbo 라는 int 형 매개변수를 받아 들인다.
 
그리고 델리게이트를 하나 선언한다.
delegate void RunDelegate(int speed);
이 델리게이트는 int 형 매개변수를 가지도록 한다
 
Go 버턴을 클릭하면 버턴 클릭 이벤트가 발생하며 이 이벤트 에서  다음과 같이 처리한다.
int turbo = 2; //전달할 파라메타

RunDelegate runDelegate = new RunDelegate(this.RunThread);

runDelegate.BeginInvoke(turbo,null,null);    

 

델리게이트를 생성하면서 참조되는 메서드를 RunThread 로 지정한다.

그리고 델리게이트의 BeingInvoke 를 호출함으로써 RunTrhead 메서드를 비동기 처리한다.

 

위 코드에서 Thread 객체는 찾아 볼 수 없다.

이것이 쓰레드 인가??????

결론저긍로 말하자면, 명시적으로 Thread 객체를 생성하지 않았을 뿐이지 내부적으로 주 쓰레드와는 별도의 호출스택을

가지며 따라서 비동기 처리가 가능하다.

 

진정 Thread 객체를 사용해야 직성이 풀린다면 아래처럼 사용하던지..

 

delegate void RunDelegate(int speed);

 

private void button1_Click(object sender, System.EventArgs e)

{                                                                                  

        ThreadStart ts = new ThreadStart(this.InvokeMethod);

        Thread thread = new Thread(ts);

        thread.IsBackground = true;

        thread.Start();                      

}                                                                   

                             

private void InvokeMethod()

{

        int turbo = 2; //전달할 파라메타

        RunDelegate runDelegate = new RunDelegate(this.RunThread);                 

        runDelegate.BeginInvoke(turbo,null,null);

}

 

#region Worker Thread 상에서 수행될 메서드(쓰레드 메서드임에도 매개변수를 가진다)

private void RunThread(int turbo)

{             

        for(int speed = 0; speed <= 100000; speed++)

        {

               this.textBox1.Text += String.Format("속도 : {0} 으로 달리고 있습니다\r\n",speed*turbo );

        }

}

#endregion

 

처음의 코드를 한번 더 랩핑한 것과 같다.

Thread 객체가 호출하는 메서드는 InvokeMethod 이며 InvokeMethod 는 또다시 RunThread 를 비동기적으로 호출한다.

결국 RunThread  가 비동기로 호출되는 것이다.

 

단, 여기서 한가지 주의할 것이 있다.

Thread.Start() -> InvokeMethod() -> RunThread () 형태로 실행될 지라도

InvokeMethod 의 쓰레드와 RunThread 의 쓰레드는 서로 다른 쓰레드 이다.

각 메서드 안에

MessageBox.Show("쓰레드 :" + Thread.CurrentThread.GetHashCode().ToString());

로 보면 서로 다른 쓰레드 임을 알 수 있다.