안녕하세요. 오늘은 Thread 구현에 대한 포스팅을 하도록 하겠습니다.
프로그램을 작성하다보면 오랜기간 하나의 프로세스를 처리하게 작성을 하게 될 수 있습니다.
이 경우 UI 프로그램일때는 로직스레드가 길게 돌아가면서 UI가 멈춘것처럼 얼어버리는 경우가 있습니다.
참으로 난감해지는 경우가 생기네요.
이것은 스래드 처리를 안해줘서 생기는 경우 입니다.
C#에서 Winform 프로그램을 만들어 실행을 하면 OS와는 별개로 자체적으로 폼도 잘 움직이고 내부 버튼이나 로직이 잘 돌아갑니다. 이 이유는 현재의 프로그램또한 OS라는 메인에서 별개의 Thread로 돌아가고 있기 때문입니다.
프로그래이 실행되면 OS로 부터 Process를 할당받아 돌아갑니다.
윈폼을 하다보면 Program.cs라는 클래스를 보게 될 것입니다.
아마 한번 열어보고 그런가보다 라고 생각을 하신 분도 계실텐데 파일을 열어보시면
위의 내용을 볼 수 있습니다.
여기가 프로그램의 메인이 되는 부분이 되겠습니다.
여기서 프로그램이 시작되며 작성한 윈폼이 스레드로 시작한다고 생각하시면 됩니다.
스레드로 시작을 하게되면 하나만 생각하다가 하나의 머리에서 두개의 생각을 한다고 생각하시면 됩니다.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Thread_Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Btn_Start_Click(object sender, EventArgs e)
{
SumProcess();
}
void SumProcess()
{
for (int i = 0; i < 10000; i++)
{
TBox_Log.AppendText($"Num : {i}" + Environment.NewLine);
}
}
}
}
대략 위와 같이 프로그램을 작성했다고 하면 위의 프로그램이 실행되어 Btn_Start 클릭하는 순간 프로그램은 반복문을 10000번 실행하면서 현재값을 UI에 표시하려 합니다.
그런데 프로그램창을 움직이려하면 움직이지 않습니다.
프로그램이 SumProcess 로직에 들어가서 끝나지 않았기 때문입니다.로직이 마무리되어 이 메서드에서 나와야만 프로그램이 화면에서 움직일 수 있습니다.
이럴때 현재 프로그램의 로직이 스레드로 돌아가게 한다면 위의 반복문이 메인 로직에서 스래드로 관리가 되어 마치 따로 동작이 하는것과 같이 됩니다.
스레드를 쓰는것은 프로그램을 작성하기 위해 필요한 요소 입니다.
이제 스레드를 사용하는 프로그램으로 변경을 해보도록 하겠습니다.
변경은 다음과 같이 하시면 됩니다.
우선 Thread를 사용하기 위해
using System.Threading;
추가 하여 Thread Class를 사용할 수 있도록 합니다.
Thread 클래스를 thread로 선언하고 기존의 SumProcess를 ThreadStart메서드의 Thread 객체 생성자의 파마미터로 입력합니다. 그리고 바로 실행하여 버튼을 누른다면
위와 같이 크로스 스레드 에러가 납니다. 이는 기존에 모든 로직이 메인으로 시작하는 하나의 스레드에서 계산로직이 UI와 다른 새로운 스레드에서 시작하기 때문입니다.
이때는 Invoke 를 사용하여 메인UI와 연결을 하여 스레드 크로스 에러를 방지할 수 있습니다.
이 방법 말고
CheckForIllegalCrossThreadCalls = false;
위의 설정으로 가능은 합니다.
하지만 예상치 못한 에러가 있을 수 있으므로 Invoke를 사용하도록 합니다.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace Thread_Test
{
public partial class Form1 : Form
{
Thread thread;
public Form1()
{
InitializeComponent();
}
void ThreadStart()
{
thread = new Thread(SumProcess);
thread.IsBackground = true;
thread.Start();
}
private void Btn_Start_Click(object sender, EventArgs e)
{
ThreadStart();
}
void SumProcess()
{
for (int i = 0; i < 10000; i++)
{
if (TBox_Log.InvokeRequired)
{
TBox_Log.Invoke(new MethodInvoker(delegate ()
{
TBox_Log.AppendText($"Num : {i}" + Environment.NewLine);
}));
}
else
{
TBox_Log.AppendText($"Num : {i}" + Environment.NewLine);
}
}
}
}
}
위와 같이하면 스레드를 통해 로직과 UI가 분리되어 움직이고 스레드 크로스 에러도 해결됩니다.
여기까지 읽어주셔서 감사합니다~
'개발' 카테고리의 다른 글
.net 9.0 migration [.net 9.0 업그레이드] (13) | 2024.11.29 |
---|---|
.Net Conf 2024 @BMW 다녀왔습니다~ (103) | 2024.11.28 |
C#으로 하는 TCP/IP 통신 -1- (101) | 2024.11.22 |
ASP.net core SignalR 해보면서 (47) | 2024.11.21 |
C# 으로 하는 RS-232 -2- (94) | 2024.11.20 |