[C# WinForm1] Main Thread/GUI Thread, Invoke

csharp 윈폼 메인 쓰레드 인보크 winform main thread gui thread invoke

왜 C# 윈폼을 선택했는가


Windows Forms를 활용한 사내 프로그램을 제작할 일이 있는데, GUI 프로그램의 전체적인 작동 원리를 공유하고자 글을 쓴다. 본인이 다니는 회사의 IT 조직은 .NET 기반의 Visual Basic.NET을 기반으로 사내 GUI 프로그램을 개발한다. 우리 팀은 IT와는 동떨어진 조직이라 언어를 그대로 차용하지는 않지만 그래도 같은 Framework을 사용해야 호환성도 고려해볼 수 있고, VB.NET과 C#은 사실상 문법만 다르지 언어 설계 자체는 거의 동일하기 때문에 기존 사내 프로그램 분석에도 유용하겠다는 판단 하에 C#을 GUI 프로그램 개발 언어로 활용 중이다. C#도 대한민국에서는 점유율이 극도로 낮은데 더 낮은 Visual Basic.NET을 메인 언어로 채택할 수는 없었음…(팀원들에게 미안하기도 하고, 어차피 해야 한다면 커리어에 조금이라도 도움이 되게 끔 하고 싶었음)

GUI 프로그램의 필수 덕목


GUI는 화면을 통해 보여지는 것이 가장 큰 목적이다. 그리고 일반 사용자가 활용하는 프로그램이다. 그러다 보니 답답하면 절대 안된다. 계속 잘 켜져 있고, 사용자의 액션에 잘 동작해야 하는 것이다. 조금이라도 지연이 있거나, 먹통(?)이 되는 순간들이 있다면 바로 불편을 호소할 것이다. 그러다 보니 내부의 로직 처리는 시간이 소요 되더라도 프로그램은 죽지 않고 동작 중이라는 티를 내야 한다.

이게 뜨는순간 사용자는 기다리지 않지…

Main Thread? GUI Thread?


그래서 GUI 화면 처리를 담당하는 스레드를 아예 따로 두고 화면만 집중해서 담당하도록 하고 이를 Main Thread 혹은 GUI Thread라고 이름 지었다. 그리고 그 이외의 스레드는 작업 스레드라고 칭한다. 복잡한 일처리는 다른 스레드를 통해서 하더라도 보여주는 것은 GUI 스레드를 통해 막힘없이 보여주도록 해라는 철학을 담고있다. GUI 프로그래밍을 잘 모른 채로 시작하면 이점을 간과하기 쉽다. 그래서 메인 스레드 내에서 모든 작업을 다 수행하게 끔 코드를 작성하게 될 것이다.

Thread Invoke에 관하여


Windows Forms에서 화면을 구성하는 GUI 구성 요소들을 Component라고 하고, 또 Control 이라고도 한다. 이 구성요소들은 모두 GUI Thread 내에 존재한다. 한 쓰레드 내에 존재하면, 다른 쓰레드 내에서 접근할 수 없다. 구성요소에 접근하여 값을 반영하려면 무조건 GUI 쓰레드여야 한다. 근데 복잡한 처리는 다른 쓰레드로 하라고 했을텐데… 이 다른 쓰레드를 통해서 GUI Control에 접근하면 반드시 Cross Thread Exception이 발생한다. 이를 해결하기 위해서 Invoke가 존재한다. Invoke의 사전적 정의는 들먹이다 이다. 다른 스레드에서는 들먹이기만 하고, 그 들먹인 것을 GUI 스레드가 듣고 대신 행하라는 것이다.

GUI 프로그램의 Lifecycle


안드로이드 gui 라이프사이클

여기서 부터는 조금 TMI인데… 그럼 GUI 쓰레드에는 무슨 Interrupt가 있나? 그래서 잘 돌고 있는 GUI 쓰레드를 통제해서 내꺼부터 처리해줘 이렇게 하나? ㄴㄴ 절대 그렇지 않다. GUI 쓰레드는 메시지 큐를 두고 이 큐에서 메시지를 꺼내 처리하는 루프를 무한정 돌리고 있다. 이를 메시지 루프라고 부르고, Control의 모든 동작은 전부 메시지로 구성되어 있어서 다 이 큐에 삽입된다. 큐에 들어오는 메시지 순서대로 작업을 수행하는 것이다. 그래서 내가 비동기나 쓰레딩을 통해 수행한 작업을 Control에 반영하는 코드를 Invoke를 통해서 작성했다면, 이 Invoke가 하는 일은 GUI 쓰레드의 메시지 루프에 대리자가 가리키는 함수를 실행하도록 하는 메시지를 삽입하고 GUI 스레드가 이 작업(메시지)이 끝나도록 기다리는 일이다. 그렇다면 작업 스레드는 오래 걸리는 일은 자체적으로 수행하고, 꼭 GUI Control에 접근해야만 하는 부분만 Invoke를 활용해 성능을 극대화할 수 있겠다.

안드로이드 GUI로 보는 공통점


아래는 안드로이드의 GUI 작업에 대한 이야기가 담긴 아티클이다. 근데, 내가 위에서 설명한 것과 거의 비슷하지 않나? 이뿐만이 아니라, JAVA GUI, Python GUI, Web GUI 등 화면에 관한 기술은 따로따로 찾아보더라도 거의 비슷할 것이다. 이렇듯 프로그래밍이라는 것은 대부분 그 아이디어는 동일하다. 구현체는 언어의 특성과 문법에 따라 가지각색 이지만… 그래서 근본이 되는 기술에 대한 명확한 이해가 있다면 다른 플랫폼, 다른 언어로 이를 구현하는 것은 크게 어렵지 않게된다. 하나를 하더라도 제대로가 가장 잘먹히는 분야가 아닌가 싶다.


Posted

in

, ,

by

Comments

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다