본문 바로가기
[ Program ]/c#스터디

53. 무명메서드

by 관이119 2022. 2. 8.

앞장에서 델리게이트를 잠시 살펴봤으니 다시 쓰레드로 넘어가보자.

 

그림1

 

그림1을 보고 잠시 생각해보자.

Thread 를 사용하기 위해 객체로 만들면 파라미터로 ThreadStart 나 ParameterizedThreadStart 를 요구한다.

둘다 객체로 만들어서 파라미터로 넘기면 되는데 마우스를 올려보면 둘다 델리게이트 인것을 알수 있다.

ParameterizedThreadStart 같은경우는 void 형(반환이 없는형태) 이고 object 를 인자로 받는 함수를 대리호출해주는 델리게이트 이다.

ThreadStart 같은경우는 void형에 파라미터가 없는 함수를 대리호출해주는 델리게이트이다.

이렇게 쓰레드를 사용하기위해서는 델리게이트가 뭔지 알아야 한다.

결국 그림1 소스 같은경우는 쓰레드를 실행하는데 그쓰레드에서 tempfunc 함수를 실행하고 파라미터 object 에는 aaaa 를 전달하는 내용이다.

델리게이트를 공부하고나서 위 소스를 보니 이제 좀더 이해가 잘될거라고 생각한다.

 

 

 

 

그림2

 

다시 델이게이트 소스로 돌아가보자. 

그림2를 보면 기본 사용형태의 델리게이트이다.

그런데 델리게이트를 추가하려면 또 함수를 추가하고 번거로운 작업이 많다.

그래서 한번만 사용할경우 복잡한 형식을 다 입력하지 않아도 되는 무명메서드라는 것이 있다.

 

그림3

 

그림3을 보면 그림2에서 델리게이트를 무명메서드로 변경해놨다.

말그대로 이름이 없이 

tempdel td = delegate (string str)
{
       MessageBox.Show(str);
};

이런식으로 함수 내부 내용을 적어놨다.

결국 그림3에서 아래 tempfunc 함수는 없어도 되는 부분이다.

델리게이트를 정의 하고 해당 형식에 맞춰서 함수만들듯이 한번 만들어서 쓰고 사라지는것이 무명메서드인것이다.

 

 

 

그림4

 

그림4처럼 간단하게 무명메서드자체를 델리게이트에 추가할수도 있다.

td += delegate (string aa)
{
        MessageBox.Show($"str is {aa}");
};

이부분인데 내용은 앞에서 이야기한 델리게이트와 중복되기 때문에 이해 될거라고 생각한다.

 

 

 

그림5

 

다음으로 그림5를 보자.

그림5에 보면

this.Invoke((tempdel2) delegate { MessageBox.Show($"Test"); });
this.Invoke((tempdel) delegate (string str) { MessageBox.Show($"Test {str}"); }, "aaaa");

두개 라인을 추가했다.

앞에 사용한 무명메서드를 더 축약한 표현인데 하나씩 뜯어보자.

두줄이 있는데 위쪽은 파라미터가 없는 함수호출하는 예제이고 아래쪽은 파라미터가있을경우의 예제이다.

 

일단 this.Invoke((tempdel2) delegate { MessageBox.Show($"Test"); }); 부터 하나씩 뜯어보자.

this 는 자기자신을 가리키는 의미로 없어도 된다.

윗줄에 있는 td.Invoke("aaa"); 와 비교하면 td 가 this 로 바꼈는데  윗줄에 있는 td.Invoke("aaa"); 는 td 라는 델리게이트를 실행한다 라는 의미이다. (이건 이미 알거라고 생각한다. 이전장에서도 이야기했다.)

그러면 this.Invoke((tempdel2) delegate { MessageBox.Show($"Test"); }); 이구문에서는 this 가 없다고 생각하면 일단 Invoke 함수를 호출한다.

 

 

그림6

 

그림6과 같이 Invoke 함수를 호출하면 2개가 오버로딩 되있는데 하나는 델리게이트를 파라미터로 받고 다른하나는 델리게이트+params 를 파라미터로 받는다.

즉, Invoke 를 호출하기 위해서 우리가 무명메서드로 만든 델리게이트를 넘겨주면 된다는 말이다.

 

다시 구문을 보면 this.Invoke((tempdel2) delegate { MessageBox.Show($"Test"); });

this.Invoke(); 함수를 호출하고 파라미터로 (tempdel2) delegate { MessageBox.Show($"Test"); } 를 넘기는 구조가 되는것이다.

파라미터로 넘긴 (tempdel2) delegate { MessageBox.Show($"Test"); } 구문을 다시 하나씩 뜯어보자.

delegate { MessageBox.Show($"Test"); } 부분만 보면 위에서 설명한 무명메서드를 만드는 형식이다.

그런데 무명메서드는 컴파일러도 어떤 형식인지 알수 없다. 

그래서 앞쪽에 (tempdel2) 로 tempdel2 형식으로 형교환만 해준것이다.

 

결론적으로 this.Invoke((tempdel2) delegate { MessageBox.Show($"Test"); }); 이문장은 무명메서드를 tempdel2 형식을 가지게 형교환해서 호출한다 는 내용이다.

구문만 보면 뭔가 복잡해 보이는데 개별적으로 다 알고 있는 내용이니 잘이해가 되지 않으면 몇번 읽어보다보면 이해할수 있을거라 생각한다.

 

다음으로 파라미터를 넘기는 두번째 문장을 보자.

this.Invoke((tempdel) delegate (string str) { MessageBox.Show($"Test {str}"); }, "aaaa");

윗문장이 이해가 됐다면 이문장도 같은내용이라서 바로 이해가 될것이다.

하나씩 다시 확인해보자.

this.Invoke 는 델리게이트를 호출한다는 의미이고, 그럼 무슨델리게이트를 호출할지 파라미터로 넘겨야한다.

호출할델리게이트는 무명메서드로 만든  (tempdel) delegate (string str) { MessageBox.Show($"Test {str}"); } 이부분이고 파라미터로 str 넘어가는 무명메서드를 tempdel 형식으로 형변환 해줬다.

그리고 마지막에 , "aaaa" 로 Invoke 함수의 두번째 파라미터인 params 에 델리게이트에서 사용할 문자를 넘겨줬다.

아래 그림7에 보면 Invoke 함수에 대한 파라미터를 표시해놨다.

 

그림7

 

추가로 델리게이트를 호출할때 MethodInvoker 라는 델리게이트를 사용할수도 있다.

위쪽에서 무명메서드를 형변환을 해줬다.

그런데 반환값이 없고 파라미터를 받지않는(viod 리턴에 파라미터없는) 델리게이트의 경우 미리정의된 MethodInvoker 델리게이트로 변환 해줄수도 있다.

 

https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.methodinvoker?view=windowsdesktop-6.0 

 

MethodInvoker Delegate (System.Windows.Forms)

Represents a delegate that can execute any method in managed code that is declared void and takes no parameters.

docs.microsoft.com

MethodInvoker 의 경우는 다른쓰레드의 컨트롤을 컨트롤할때 자주 사용하게 될테니 꼭 기억하고 넘어가자.

 

 

무명메서드를 살펴봤으니 다시 잠시 쓰레드로 넘어가보자.

 

 

그림8

 

그림8을 보면 단순한 쓰레드를 호출하는 구문이다. 

그런데 쓰레드 파라미터로 뭘 받는지 잘생각해보자.

ParameterizedThreadStart 나 ThreadStart 라고 미리 정의된 델리게이트 였다.

 

그림9

 

ThreadStart 에서 마우스 우클릭해서 정의로 이동해보자.

그러면 그림9 처럼 Threading 네임스페이스 내에 미리 정의된 델리게이트 였다.

그렇다면 쓰레드에 파라미터로 무명메서드를 넣으면 되지않을까?

결론적으로 된다.

다음코드를 보자.

 

그림10

 

그림10을 보면 위쪽에 기존 ThreadStart 대신 아래에서 무명메서드를 직접넣어서 호출한 코드가 보인다.

Thread t = new Thread(delegate() { MessageBox.Show("Test");});

이구문인데 물론 정상작동한다.

그러면 이제 파라미터 넣는 예제를 한번 더 해보자.

 

 

그림11

그림11에 보면 ParameterizedThreadStart 델리게이트 정의를 따라가서 확인한 내용이다.

ParameterizedThreadStart 는 파라미터를 object 하나 받는 델리게이트이다.

그래서 쓰레드에서 파라미터를 받는 예제를 만들려면 똑같이 object 파라미터 하나를 넘기는 무명메서드를 정의해주면 될것이라고 생각할 수 있다.

 

 

그림12

 

그림12를 보면 파라미터 하나를 무명메서드로 넘기는 경우와 ParameterizedThreadStart 로 넘기는 경우 두가지를 예제로 만들어 놨다.

 

이렇게 전체적으로 무명메서드를 살펴봤는데 복잡해보이지만 결국 다 같은내용이고, 사용하는 내장함수에서 요구하는 파라미터만 넘겨주면 어렵지않게 사용할수 있다는것을 알수 있다.

다음장에서 확인해볼 람다식까지 전체적으로 쓰레드를 사용하면서 자주 접하게 될 내용이기 때문에 꼭알아두자.

 

 

 

***숙제 : 버튼을 누르면 두개의 쓰레드에서 각각 무명메서드를 사용하여 100이하의 짝수와 홀수의 합을 각각 출력하는 프로그램을 만들어보자.

 

'[ Program ] > c#스터디' 카테고리의 다른 글

55. Action/Func  (0) 2022.02.22
54. 람다식  (0) 2022.02.17
52. 델리게이트  (0) 2022.02.05
51. 쓰레드1(Thread)  (0) 2022.02.04
50. 전처리기 / 편의사항  (0) 2021.10.29

댓글