C#

스레드 문제점 해결

윤태영(Coding) 2023. 6. 14. 23:23

멀티스레딩을 사용하면 한 프로세스 내에서 여러 개의 작업을 동시에 처리할 수 있다. 하지만 이런 스레드들을 잘 관리하지 않으면 리소스가 해제되지 않는 문제가 발생할 수 있다.

 

이는 시스템 자원을 불필요하게 점유하게 되어 프로그램의 성능을 저하시키거나 메모리 누수 같은 문제를 발생시킬 수 있다.

< 스레드의 자원을 제대로 해제하는 두 가지 방법 >

[Background 속성 이용]
스레드는 기본적으로 Foreground 스레드로 생성된다. 때문에 메인(UI) 스레드가 종료되어도 해당 스레드는 계속 실행된다. 하지만 Background 스레드로 설정하면 메인 스레드가 종료될 때 해당 스레드도 함께 종료되어 자원을 해제하게 된다.

 Thread.IsBackground = true;를 통해 해당 스레드를 Background 스레드로 설정할 수 있다.이렇게 하면 해당 스레드가 프로그램이 종료되는 시점에서 함께 종료되도록 한다.

[Form Closing]
Form이 종료되는 시점에 작동하는 이벤트인 Form Closing을 이용해 스레드의 자원을 해제할 수도 있다. 만약 Form이 닫히는 시점에 생성된 스레드가 아직 실행 중이라면 해당 스레드를 종료하고 자원을 해제하는 코드를 작성한다. 이를 통해 스레드가 더 이상 필요하지 않은 시점에 정확하게 스레드를 종료하고 자원을 회수할 수 있다.

< 실습 >

아래와 같이 코드를 작성하고 솔루션 빌드 후, 실행을 하고 Form1 창을 닫았다. 그러면 정말 종료가 된 것일까?

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        Thread th = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //쓰레드 자원할당
            th = new Thread(new ThreadStart(methodStart));
            th.Start();//쓰레드가 실행 
        }
        private void methodStart()
        { 
          while(true) 
            { 
                //1초씩 쓰레드가 멈추도록 
                Thread.Sleep(1000);

            }
        }
    }
}

위의 코드를 실행 하고, Form1 창을 닫아 보았다.

 

창을 닫으면, WinFormsApp1이 실행 종료가 된 줄 알았는데 작업관리자에 가보니, Background에서 여전히 실행 중인 것을 알 수 있다.

즉, 아래의 스레드 부분이 계속 실행이 되고 있다는 것이다.

이럴 경우 작업관리자에서 직접 프로세스를 종료를 해줘야한다. 이러한 현상이 일어나는 이유는 스레드 리소스를 해제를 안했다는 것이다.

 

이때 Thread.IsBackground = true;를 사용하게 되면, 창을 닫으면 프로세스도 같이 종료가 되는 것을 확인할 수 있다.

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        Thread th = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //쓰레드 자원할당
            th = new Thread(new ThreadStart(methodStart));
            th.IsBackground = true;
            th.Start();//쓰레드가 실행 
        }
        private void methodStart()
        { 
          while(true) 
            { 
                //1초씩 쓰레드가 멈추도록 
                Thread.Sleep(1000);

            }
        }
    }
}

※ 주의 사항 Form1에서 Form2를 생성하고, Form2를 실행하도록 하고,

Form2에 th.IsBackground = true;를 설정하면, 스레드가 종료가 될 줄 알았는데, 종료가 안된다.

이유는  UIThread 즉, Program.cs에서 Form2로 변경해야지만, 삭제가 된다.

 

 이렇게 IsBackground를 사용하기 보다는 다시 new Form2를 Form1으로 원상복구 한 뒤,

Form2가 닫히면, 스레드가 종료되도록 하고 싶다면 이때 Form Closing 방법을 쓸 수 있다. 

 

Reference : C#.NET 0.5년차~3년차(파트1)

이 블로그의 모든 내용은 원작자와 출판사로부터 허락을 받아 작성되었습니다.

https://www.inflearn.com/course/lecture?courseSlug=%EB%8B%B7%EB%84%B7-%EC%9C%88%ED%8F%BC-1&unitId=77888&tab=curriculum