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
{//같은 쓰래드다.
}
다른 스레드일 때는 인보크를 해야 하고 같은 스레드일 때는 필요 없습니다.
매번 'InvokeRequired'와 'Invoke'를 써가며 코드를 만드는 건 유지보수성이 떨어집니다.
아래 함수를 재사용하기 쉽도록 적절한 위치에 선언하여 사용합시다.
/// <summary>
/// 크로스 스레드 체크를 하고 상황에 맞게 처리한다.
/// </summary>
/// <param name="controlThis"></param>
/// <param name="action"></param>
public static void CrossThread_Winfom(Control controlThis, Action action)
{
if (true == controlThis.InvokeRequired)
{//다른 쓰래드다.
controlThis.Invoke(new Action(
delegate ()
{
action();
}));
}
else
{//같은 쓰래드다.
action();
}
}
테스트 프로젝트 : github - dang-gun/DotNetSamples/CrossThreadTest_Winfom
검색하다가 안 사실이지만 의외로 델리게이트를 간략화해서 쓰는 걸 모르시는 분들이 많으시군요.
액션 같은 것은 무명 메서드로 사용할 수 있으니 잘 활용해 봅시다.
제 기억으론 책에서도 나왔던 거 같은데;;;(아닌가?)
이럴 줄 알았으면 빨리 포스팅하는 거였는데 말이죠 ㅎㅎㅎㅎ