블로그 이미지
Kanais
Researcher & Developer 퍼즐을 완성하려면 퍼즐 조각들을 하나 둘씩 맞춰나가야 한다. 인생의 퍼즐 조각들을 하나 둘씩 맞춰나가다 보면 인생이란 퍼즐도 완성되는 날이 오려나...?

calendar

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

Notice

05-01 06:35

Recent Post

Recent Comment

Recent Trackback

Archive

2015. 5. 28. 13:35 Programming/.NET


작성날짜 : 2011-05-11

수정날짜 : 2015-05-28





Delegate 
실습

 

시나리오

l  실행하면 먼저 ParentForm 창이 뜨고 현재 시간을 보여준다.

l  추가 버튼을 누르면 ChildForm 창이 뜨고 텍스트박스에 이름을 입력하고 추가 버튼을 누르면 추가된 멤버 수가 증가 된다.

l  ChildForm 창을 닫으면 ParentForm ListView  ChildForm 에서 추가한 이름들이 전부 추가되어 보여준다.

 

ParentForm 

 




 

ChildForm 

 


Parent.cs

public partial class Parent : Form

{

    System.Timers.Timer timer = null;

    private delegate void ViewNowTimeDelegate(string date);

    public Parent()

    {

        InitializeComponent();

        CurrentTime();

    }

    private void CurrentTime()

  {

      timer = new System.Timers.Timer(1000);

        timer.Elapsed +=

new System.Timers.ElapsedEventHandler(timer_Elapsed);

      timer.Enabled = true;

    }

    void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)

    {

        DateTime now;

        now = DateTime.Now;

        ViewNowTime(now.ToLongTimeString());

    }

    private void ViewNowTime(string p)

    {

        //labelOfTime.Text = p;

        if (this.InvokeRequired == false)

        {

            labelOfTime.Text = p;

        }

        else

        {

            ViewNowTimeDelegate viewtime =

new ViewNowTimeDelegate(ViewNowTime);

            object[] t = new object[] { p };

            this.BeginInvoke(viewtime, p);          //비동기

            //this.Invoke(viewtime, t);             //동기

        }

    }

    private void buttonOfAdd_Click(object sender, EventArgs e)

    {

        Child f2 = new Child();

        f2.MemEventHandler += new MemberEventHandler(f2_MemEventHandler);

        f2.ShowDialog();

    }

    void f2_MemEventHandler(System.Collections.ArrayList mans)

    {

        foreach (Man man in mans)

        {

            listViewOfMember.Items.Add(man.Name);

        }

    }

}

 

Child.cs

public delegate void MemberEventHandler(ArrayList mans);

public partial class Child : Form

{

    public event MemberEventHandler MemEventHandler = null;

    ArrayList mans = new ArrayList();

    int count = 0;

  public Child()

    {

        InitializeComponent();

    }

    private void buttonOfAdd_Click(object sender, EventArgs e)

    {

        ++count;

        AddMan();

    }

    private void AddMan()

    {

        Man man = new Man();

        man.Name = textBoxOfName.Text;

        mans.Add(man);

        textBoxOfName.Text = string.Empty;

        labelOfCount.Text = count.ToString();

    }

    private void Form2_FormClosed(object sender, FormClosedEventArgs e)

    {

        if (MemEventHandler != null)

        {

            MemEventHandler(mans);

        }

    }

}

 

실행 화면

실행하고 ParentForm 창에서 추가버튼을 누르면 ChildForm 창이 뜹니다그리고 ChildForm에서 이름을 입력하고 추가버튼을 누르면 추가된 멤버 수 count가 증가되고 ArrayList에 추가가 됩니다그리고 ChileForm을 닫으면 ParentForm ListBox ChildForm에서 추가했던 이름들이 뜨는 것을 확인 할 수 있습니다.

 

 



크로스 스레드 해결방법

참고 사이트 : MSDN | http://msdn.microsoft.com/ko-kr/library/ms171728

버닝워커 블로그 http://blog.naver.com/kkdcool?Redirect=Log&logNo=110054020805

 

크로스 스레드 해결방법에는 3가지가 있다. InvokeRequired 속성을 사용하는 방법, BackgroundWorker를 이용하는 방법, CheckForIllegalCrossThreadCalls = false의 방법이 있습니다그 중 InvokeRequired 속성을 사용하여 해결하였습니다.

 

Parent클래스에서 ViewNowTime 메소드를 보면 아래와 같이 주석처리된 부분이 있는 것을 볼수 있다.


//labelOfTime.Text = p;


만일 이 부분을 주석 처리하지 않고 나머지 부분을 주석처리 한 후 실행해 보면 다음과 같은 에러를 볼 수 있을 것이다.

 

 

하나의 컨트롤에는 하나의 스레드만 작업을 수행할 수가 있는데. labelOfTime 컨트롤을 Parent Form의 스레드가 작업을 수행하려 했기 때문에 에러가 난 것이다이에 대한 해결 방안으로 Invoke를 써서 해결하였는데, Invoke를 설명하기에 앞서 InvokeRequired 속성먼저 설명하겠다. MSDN에는 ’InvokeRequired 속성에 대하여 호출자가 컨트롤이 만들어진 스레드와 다른 스레드에 있기 때문에 메서드를 통해 컨트롤을 호출하는 경우 해당 호출자가 호출 메서드를 호출해야 하는지 여부를 나타내는 값을 가져옵니다. 라고 설명되어 있다그리고 속성 값에 대해서 컨트롤의 Handle이 호출 스레드와 다른 스레드에서 만들어져 호출 메서드를 통해 해당 컨트롤을 호출해야 하는 경우 true이고그렇지 않으면 false입니다. 라고 설명 되어 있다호출 메서드를 통해 해당 컨트롤을 호출하지 않을 경우 labelOfTime에 p값을 대입해 주고 그렇지 않을 경우 Invoke를 사용하여 처리하면 된다. ViewNowTimeDelegate 개체를 생성하고 동기식으로 하려면 Invoke를 비동기식으로 하려면BeginInvoke를 사용하면 된다.

 

InvokeRequired 속성에 대한 참고 : MSDN - Control.InvokeRequired 속성 



'Programming > .NET' 카테고리의 다른 글

[ADO.NET] XmlReader - AttributeCount 속성  (0) 2015.06.05
[ADO.NET] XmlReader 소개  (0) 2015.06.05
[.NET] Assembly - 2  (0) 2015.05.19
[.NET] Delegate (대리자) - 2  (0) 2015.05.19
[.NET] DataRepeater Control  (0) 2015.05.19
posted by Kanais