요즘 delegate랑 thread를 열심히(?) 공부하고 있습니다..
나름 좀 이해가 된다고 생각은 되지만
언제 어떻게 적용하면 좋을지는 아직 잘 모르겠네요..;;;;

예제 코드는 이렇습니다.
일단 비동기로 호출할 Add 메서드가 있습니다.


public static int Add(int op1, int op2, out int result)
{
    Console.WriteLine("[Add] 시작...");
    Thread.Sleep(3000);
    Console.WriteLine("[Add] 끝...");
    return (result = op1 + op2);
}

중간 중간 화면에 하고 있는걸 보여주고
실제로 뭔가 하는거 처럼 보이도록 Thread.Sleep 을 해줍니다.


그리고 delegate도 하나 선언해 줍니다.

public delegate int AddDelegate(int op1, int op2, out int result);

이 delegate는 위에 있는 Add메서드와 signature가 같습니다.

그리고 다음과 같은 메인코드가 있습니다.

static void Main(string[] args)
{
    int result;

    AddDelegate add = new AddDelegate(Add);

    Console.WriteLine("[Main] 비동기로 Add메서드 Invoke");
    IAsyncResult iAR = add.BeginInvoke(6, 42, out result, null, null);  

    Console.WriteLine("[Main] 뭔가 하는거 처럼 보이도록...");

    for (int i = 0; i < 10; i++)
    {
        Thread.Sleep(200);
        Console.Write(".");
    }

    Console.WriteLine("\n[Main] Add메서드가 끝날때 까지 대기...");
    iAR.AsyncWaitHandle.WaitOne();
    Console.WriteLine("[Main] Add메서드 종료");

    add.EndInvoke(out result, iAR); 
    Console.WriteLine("[Main]  result 는 '{0}'", result);
    Console.ReadLine();
}




메인에서는 delegate에 메서드를 넣어서 만들어 주고
BeginInvoke해 줍니다.
(BeginInvoke의 네번째와 다섯번째 파라미터는 callBack과 위임 객체에 접근하기 위한 참고객체 입니다.)
그러면 Add메서드를 호출하는 작업스레드를 생성해 주고 IAsyncResult객체를 반환해 줍니다.
그 객체는 iAR에 들어가겠죠

중간에 들어있는 for문은 그냥 메인도 뭔가 하는거 처럼 보이게 하기위한 코드 입니다.

그리고 반환받은 IAsyncResult객체를 이용해서
스레드가 끝날 때 까지 대기 하도록 WaitOne을 호출 해 줍니다.

그 후에 EndInvoke를 이용해서 결과값을 반환 받습니다.
EndInvoke는 Add메서드와 동일한 반환값을 가지므로
result를 out으로 안해도 값을 받아올 수 있습니다.

간단해 보이는데
참 난감하네요. ;;

by 피요히코~ 2010. 10. 8. 16:44
이거저거 하다보면
여러 컨트롤들을 합친 유저컨트롤을 쓸 때가 있습니다.
(뭐 TextBox와 ComboBox를 합친다든지 하는...)
의도에 맞춰서 잘 쓰려면
적절하게 속성도 만들어서 노출시켜야 할꺼고
이벤트도 있어야 할텐데요

간단하게 유저컨트롤에 이벤트를 만들어 보는걸 정리해보겠습니다.
(누군가가 와서 볼꺼라는 생각에 힘들게 존댓말로 글을 쓰지만. 방문자수는 안습. ㅋㅋ)

아주 초 간단하게
그냥 유저컨트롤에 버튼 한개만 (딸랑..)넣어서 작성해보죠
겉보이게는 그냥 버튼과 차이가 없지만
사실 제일 위에는  UserControl이 있고 그 안에 버튼이 있고. Dock이 Fill로 되어 있는겁니다.. ㅋ

이제 이 컨트롤을 사용할때
속성창에서 노출될 이벤트를 만들어줍니다.


[Description("클릭이벤트지롱"), Category("속성이지롱")]
public event EventHandler NewClick;

Description은 속성창에서 해당 속성을 클릭했을때 나오는 설명이고
Category는 해당 속성이 들어있는 카테고리를 설정해 주는겁니다.
그리고 NewClick이라는 새로운 EventHandler를 하나 만들어줍니다.

이렇게 해주고 나중에 이놈을 다른 창에 얹고 클릭해서 속성을 보면



보시다시피 중간에
"속성이지롱" 카테고리에
"NewClick"이라는 이벤트가 보이고
아래쪽에
"클릭이벤트지롱" 이라는 설명이 보입니다. ㅋ

그 다음에는 유저컨트롤 안에서 버튼 클릭이벤트를 만들어준후에
그 이벤트와 새로 만들었던 이벤트핸들러를 연결해 줍니다.
private void button1_Click(object sender, EventArgs e)
{
        MessageBox.Show("클릭");
        OnClick(sender, e);
}

public void OnClick(object sender, EventArgs args) //2
{
        if (NewClick != null)
        {
                Invoke(NewClick, null);
        }
}


button1_Click은 유저컨트롤 안에 있는 버튼의 이벤트고
해당 이벤트 발생시에
OnClick을 호출하도록 했습니다.

OnClick안에서는 이벤트핸들러인 NewClick이 null이 아니면 호출하도록 해줬습니다.

이러면 끝이에요! ㅋ

그리고 다른 컨트롤(기본컨트롤들)처럼 추가해서 NewClick이벤트란을 더블클릭해서 자동으로 이벤트를 만들고
안에 코드를 넣어주면
제대로 잘 돌아갑니다.
public UserControlTest()
{
        InitializeComponent();
        this.ucTest1.NewClick += new EventHandler(ucTest1_NewClick);
}

void ucTest1_NewClick(object sender, EventArgs e) 
{
        MessageBox.Show("여기서클릭");
}


이렇게 하고 실행해서
버튼(처럼 보이는 유저컨트롤)을 클릭하면
"클릭" 과 "여기서클릭" 메시지가 빠방~! 하고 뜹니다.

이걸 순서대로 한번 정리를 해보면요
처음에 유저컨트롤에 있는 버튼을 클릭을 하면
유저컨트롤안에 있는 버튼의 클릭이벤트가 발생해서
button1_Click 이놈이 호출 되겠죠
그리고 "클릭"을 뜨게 한다음에
OnClick을 호출해 줍니다.

OnClick에서는 이벤트핸들러인 NewClick이 null이 아니면
그 놈을 호출해 주는데

보시다 시피
this.ucTest1.NewClick += new EventHandler(ucTest1_NewClick);
이렇게 NewClick 이벤트핸들러에 ucTest1_NewClick 이놈을 += 해줬기 때문에
null이 아닐꺼고
실행이 되겠죠

그러면 ucTest1_NewClick 이놈이 호출되서
"여기서클릭"이 빠방! 하고 또 뜨게 되는겁니다.

음..
전 이렇게 이해했는데
맞을랑가 모르겠네요. ㅋ
by 피요히코~ 2010. 7. 21. 16:36
| 1 |