3_c#/Winform

C# Winform 크로스 스레드 해결

Mi:sAng 2024. 1. 31. 02:45

윈도우 GUI 프로그래밍의 기본 규칙 중 하나는

[컨트롤을 만든 스레드만 컨트롤의 내용에 접근하거나 수정할 수 있다.]

 

Winform에서 폼은 메인 스레드에 의해 구동이 되고 있다.
이 원칙 하에 발생하는 에러가 크로스 스레딩이다. UI 작업하면서 많이 발생하는데, 
UI에 접근하려면 UI를 만든 스레드만이 접근해야한다. 다른 스레드가 접근하면 안된다는 것.
이 문제를 해결하기 위헤 invoke 함수 사용

 

Invoke (누구의 이름을)부르다 라는 뜻이다. 
하나의 Form을 다른 스레드에서 접근하게 될 경우에 기존의 Form과 충돌이 날 수 있다.
이때 invoke 함수를 사용해서 실행하고자 하는 메소드의 대리자(델리게이트)를 실행한다. 
델리게이트는 메소드를 참조하는 대리자이다. 약간 함수포인터 같은 느낌.
크로스 스레드 문제를 해결할 때 Invoke함수와 델리게이트 조합으로 해결한다. 

 

어떻게 보면 어떤 [스레드 A]가  [스레드B]가 만든 UI마주할 때 마다

[스레드B]에게 주소찍고 직접 그 함수를 실행해줘~!  라고 하는 방식이다.

 

InvokeRequired는 true인 경우는 UI를 생성한 스레드와 호출한 스레드가 다르다는 것.

Control.Invoke : 컨트롤의 내부 핸들이 있는 스레드에서 지정된 대리자를 실행하는 방법
Visual Studio설명란 

 

 

예제)

private void WriteTextSafe(string text)
{
    if (textBox1.InvokeRequired)
    {
        Invoke((MethodInvoker) delegate() {
            WriteTextSafe(text);
        });
    }
    else
    {
        textBox1.Text = text;
    }
}

private void textBoxShow()
{
    if(richTextBox1.InvokeRequired)
    {
        richTextBox1.Invoke(new MethodInvoker(delegate { richTextBox1.Text = "Button Clicked !!"; }));
    }
    else
        richTextBox1.Text = "Button Clicked !!";

}