출처 : http://blog.danggun.net/2040
WCF가 예전에 사용하던 방식과 달라 이것저것 테스트 하다가 간만에 뜬 에러
크로스 스레드 작업이 잘못되었습니다.
아....
예전에 WPF에서 한번 소개 하긴 했었습니다만 윈폼에서는 약간다르죠.
(참고 : [WPF] 다른 쓰레드에서 UI쓰레드 접근하기 - Dispatcher.Invoke)
일반적으로 인보크(Invoke)를 사용하려면 델리게이트(Delegate)를 만들어야 합니다.
(참고 : MSDN - Control.Invoke 메서드)
일반적인 방법에서는 다음과 같은 순서로 인보크를 사용합니다.
1) 델리게이트 선언
2) 델리게이트에 연결할 함수 생성
3) 델리게이트와 생성한 함수 연결
4) 인보크로 델리게이트 호출
//1) 델리게이트 선언 /// <summary> /// 델리게이트 선언(연결 할 함수와 같은 모양이 되도록 만든다.) /// </summary> /// <param name="sData"></param> private delegate void DataDelegate(string sData); //2) 델리게이트에 연결할 함수 생성 /// <summary> /// 실제 동작하는 함수(연결 할 함수) /// </summary> private void DelegteFuntion(string sData) { label2.Text = sData; } //3) 델리게이트와 생성한 함수 연결 //4) 인보크로 델리게이트 호출 //사용할때 this.Invoke(new DataDelegate(DelegteFuntion), "Test!");
이 방법의 가장큰 문제는 원하는 동작만큼 델리게이트를 선언해야 한다는 것입니다-_-;;;;;
그래서 간소화 방법을 사용하죠.
간소화 방법은 일반적인 방법과는 달리 한줄로 델리게이트를 선언하는 방법 입니다.
메소드인보커 대리자(MethodInvoker Delegate)를 이용하는 방법이죠.
(참고 : MSDN - MethodInvoker 대리자)
this.Invoke(new Action( delegate() { label2.Text = "Test"; })); //혹은 this.Invoke(new MethodInvoker( delegate() { label2.Text = "Test"; }));
깔끔하게 됐죠?
메소드인보커를 이용하면 델리게이트를 전역으로 선언하지 않고 사용할수 있습니다.
단 해당 데리자를 따로 저장하지 않으면 1회만 사용할 수 있습니다.
하지만 자신의 쓰래드에서 인보크를 시도하면 에러가 납니다.
이걸 해결하려면 'InvokeRequired'속성을 써야 합니다.
'InvokeRequired'속성은 'System.Windows.Forms'에 속해있는 속성으로 호출된 메소드가 같은 쓰래드인지 아닌지 확인해 줍니다.
if( true == InvokeRequired) { //다른 쓰래드다. } else { //같은 쓰래드다. }
다른 쓰래드일때는 인보크를 해야하고 같은 쓰래드일때는 필요없습니다. ㅇㅇㅇㅇㅇㅇ
검색하다가 안 사실이지만 의외로 델리게이트를 간략화 해서 쓰는걸 모르시는 분들이 많으시군요 ㅡ.ㅡ;;;
제 기억으론 책에서도 나왔던거 같은데;;;(아닌가?)
이럴줄 알았으면 빨리 포스팅을 하는 거였는데 ㅡ,.ㅡ;;;