일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- PHP
- html5
- 안드로이드 푸쉬
- 자바스크립트
- Mail Server
- 안드로이드
- WebView
- UML
- dovecot
- 자동 생성
- roundcube
- C#
- 폼메일
- 안드로이드 gcm
- 안드로이드 푸시
- not working
- javascript
- chart.js
- curl
- mysql
- C# IO
- FCM
- php 시큐어코딩
- xe
- php 취약점
- soundpool
- 설치
- 우분투
- Android
- android 효과음
- Today
- Total
그러냐
[C#]Control클래스의 Invoke 메소드로 익명메소드 사용방법 본문
|
Written by 김영일(Youngil Kim), C# Developer
C# 2.0에서는 익명메소드라는 기능이 있는데 이를 이용하면 여러개의 메소드로 나누어서 처리해야할 것을 1개로 정리할 수 있는 기능입니다.
그러나, Control클래스의 Invoke메소드 파라미터로서 익명메소드를 만들면 컴파일시 오류가 납니다.
- 익명 메소드 사용법
Thread 클래스에 의해 다른 스레드로 처리를 할 경우 , C# 1.1에서는 다음과 같이 사용합니다.
void Run() {
ThreadStart ts = new ThreadStart(worker);
Thread t = new Thread(ts);
t.Start();
}
void worker() {
Console.WriteLine("스레드 실행중...");
}
위 코드에서는 Thread클래스는 Delegate 객체(ts)를 경유해 worker메소드를 호출합니다. ThreadStart형은 Delegate형이며 System.Threading 네임스페이스에서 다음과 같이 정의합니다. 이것은 worker메소드와 같이 리턴값이 없고 파리미터도 취하지 않는 메소드에 대해서 이용할 수 있는 Delegate형입니다.
public delegate void ThreadStart();
그런데 이를 C# 2.0의 익명메소드를 이용하면 아래와 같이 한개의 메소드를 정리할 수 있습니다.
void Run() {
Thread t = new Thread(
delegate() {
Console.WriteLine("스레드 실행 중...");
}
);
t.Start();
}
위 예제에서 delegate() { }부분이 익명메소드로 C# 2.0의 컴파일러에 의해 Delegate객체로 옮겨진다고 보면 됩니다. Delegate경유로 로드되는 메소드의 내용이 간단한 경우에는 익명메소드를 사용하는 것이 코드의 가독성도 높여 줄 수 있습니다.
- System.Delegate형 파라미터를 받는 Control.Invoke메소드
위의 예제는 스레드 실행에 대한 것이지만 윈폼 응용프로그램 개발시, 개별 스레드로 실행되는 코드로부터 폼의 컨트롤을 조작하기 위해 Invoke메소드를 사용하는 경우 다음과 같습니다. 참고로 System.Windows.Forms 네임스페이스의 Control클래스의 메소드, 폼이나 모든 컨트롤은 메소드를 상속받으며 Invoke메소드를 사용하려면 파라미터로 지정한 Delegate메소드를 메인 스레드로 실행할 수 있습니다.
delegate void SetFocusDelegate();
void SetFocus()
{
// 메인 스레드로 실행하고 싶은 처리부분
}
void worker()
{
// this는 폼의 인스턴스를 참조한다는 것임
this.Invoke(new SetFocusDelegate(SetFocus));
}
물론 C# 2.0에서는 위에서는 익명메소드를 사용할 수 있지만 아래와 같이 고치면 컴파일시 오류가 납니다.
void worker()
{
Invoke(
delegate() {
// 메인스레드로 실행하고 싶은 처리
}
);
}
위의 경우 Invoke메소드의 파리미터는 System.Delegate형이 아니면 안되지만 익명메소드는 이 형태에서 케스트를할 수 없기 떄문에 오류가 납니다. 이 오류를 수정하려면 Delegate형에 익명메소드를 케스트해주면 됩니다.
delegate void SetFocusDelegate();
void worker()
{
Invoke(
(SetFocusDelegate) delegate() {
// 메인 스레드로 실행하고 싶은 처리
)};
}
<Invoke 메소드로 익명메소드를 사용하는 경우>
System.Windows.Forms 네임스페이스에는 리턴값이 없고 파라미터도 얻지 않은 메소드에 대해서 이용가능한 Delegate형으로서 MethodInvoker형이 미리 정의되어 있습니다. 윈폼 응용프로그램이면 위 예제에는 이 MethodInvoker형을 이용할 수 있습니다
void worker()
{
Invoke(
(MethodInvoke) delegate() {
// 메인 스레드로 실행하고 싶은 처리
}
);
}
<MethodInvoker형을 사용한 Invoke메소드에 의한 익명 메소드 사용>
그런데 왜 이런 캐스트가 필요할까요?
- Delegate형이 아닌 System.Delegate형
위 문제점은 다음과 같은 심플한 코드로 나타낼 수 있습니다. 물론 이 코드도 컴파일 오류가 납니다.
using System;
class Program {
static void Main() {
Delegate d = delegate() { }; // 컴파일 오류
// Delegate형은 아니기 때문에 익명메소드 블록을 System.Delegate로 변환할 수 없음
}
}
이 오류는 System.Delegate형은 Delegate형이 아니기 때문에 컴파일러는 익명메소드의 구체적인 형을 알 수 없다는 의미입니다.
익명메소드를 사용하는 경우 그 구체적인 Delegate형이 정확하지 않으면 안됩니다. 그러나 System.Delegate형은 추상형이고 구체적인 Delegate형이 아니기 때문에 위 예제는 오류가 납니다.
위 예제를 컴파일이 잘되도록 구성하려면 익명메소드를 캐스트해야 할 필요가 있습니다.
using System;
using System.Windows.Forms;
class Program {
static void Main() {
Delegate d = (MethodInvoker) delegate() { };
}
}
참고로 모든 Delegate형은 System.Delegate형으로부터 파생됩니다. Invoke메소드의 파라미터가 System.Delegate형인 것은 어떤 Delegate형의 인스턴스에서도 받을 수 있게 하기 위한 것같습니다.
'c#' 카테고리의 다른 글
C# Socket 클레스를 이용한 바이트단위 Socket 프로그램 (0) | 2016.01.28 |
---|---|
Invoke , BeginInvoke, MethodInvoker (2) | 2016.01.28 |
스레드 간 컨트롤 접근과 스레드 동기화 1탄 (0) | 2016.01.28 |
한글 들어있는 개수 리턴하는 함수 (0) | 2016.01.28 |
정규식 ( regular expression) (0) | 2016.01.28 |