본문 바로가기

C# 개인 공부 기록용/Memo

Thread 종료시 주의 사항 (내 기준)

대부분의 스레드는
메인 스레드외에 병렬 작업 및 while문으로
무언가를 계속 수행해야 될때 주로 사용한다
(내 기준)

아래 시리얼 포트 통신에 관한 한부분의 코드를 예를 들어보자면
내가 송신한 명령값 즉 TX 대한 RX값을 주기적으로 계속 받아와야 하므로 while문을 사용했다.

        #region --> Read 스레드
        internal Thread read_Thread = null;

        bool is_Continue_Read_Thread = true;

        public void Stop_Read_Thread()
        {
            is_Continue_Read_Thread = false;
        }

        /// <summary>
        /// 패킷을 송신 했을때 수신 가능한 RX값이 있다면 RX큐에 저장된 RX값을 가져오는 기능의 스레드
        /// </summary>
        private void Read_Thread_Pkt()
        {
            byte[] read_Pkt = new byte[256]; // 수신 패킷
            int read_Pkt_Idx = 0; // 수신 패킷 길이

            bool is_RX_Exist = false; // RX 존재 여부
            byte RX = 0;

            while (is_Continue_Read_Thread == true)
            {
                #region ----> 수신된 문자가 있을 때까지 대기 (RX값 유무)
                is_RX_Exist = Get_Rx_Queue_Byte(out RX);

                if (is_RX_Exist == false)
                {
                    ClassApp.Sleep(10);
                    // 밑에 문장은 실행하지 않고
                    // 반복문 맨 첨으로 continue
                    continue;
                }
                #endregion

                // 스텝의 단계에 따라
                switch (read_Step)
                {

                    /* 송신 세트 순서
                     * 1. TX --> ENQ        0x05
                     * 2. RX --> DLE 0      0x10 0x30
                     * 3. TX --> TEXT       CMD
                     * 4. RX --> DLE 1      0x10 0x31
                     * 5. TX --> EOT        0x04
                     */

                    #region ----> 송신 세트
                    case READ_STEP.SEND_ENQ:
                        if (RX == 0x10)
                        {
                            read_Pkt[read_Pkt_Idx] = RX;
                            read_Pkt_Idx++;

                            read_Step = READ_STEP.READ_DLE0;
                        }

                        #region ------> Non Receptible State
                        else if (RX == 0x04)
                        {
                            // 재시도할지? 대기상태로 갈지?
                            read_Step = READ_STEP.IDLE;
                        }
                        #endregion
                        break;

                    case READ_STEP.READ_DLE0:
                        if (RX == 0x30)
                        {
                            read_Pkt[read_Pkt_Idx] = RX;
                            read_Pkt_Idx++;
                            Log(read_Pkt, read_Pkt_Idx, true);
                            Receive_Packets_To_Main_Screen_Log(read_Pkt, read_Pkt_Idx, "DLE0");
                            read_Pkt_Idx = 0;

                            // ★ TEXT 송신 ★
                            Send_Packet(CMD_Value);

                            read_Step = READ_STEP.READ_DLE1_10;
                        }
                        break;

                    case READ_STEP.READ_DLE1_10:
                        if (RX == 0x10)
                        {
                            read_Pkt[read_Pkt_Idx] = RX;
                            read_Pkt_Idx++;

                            read_Step = READ_STEP.READ_DLE1_31;
                        }
                        break;

                    case READ_STEP.READ_DLE1_31:
                        if (RX == 0x31)
                        {
                            read_Pkt[read_Pkt_Idx] = RX;
                            read_Pkt_Idx++;
                            Log(read_Pkt, read_Pkt_Idx, true);
                            Receive_Packets_To_Main_Screen_Log(read_Pkt, read_Pkt_Idx, "DLE1");
                            read_Pkt_Idx = 0;

                            // ★ EOT 송신 ★
                            #region ------> EOT 송신
                            Send_EOT(); 
                            #endregion

                            read_Step = READ_STEP.READ_ENQ;
                        }
                        break;
                    #endregion

 

스레드가 다 끝나고 포트 연결을 끊어서 종료시키는 것은 문제가 되질 않지만
항상 예외라는 것이 있듯이 스레드 동작중 중간 어디선가 포트 연결이 끊으면 문제가 될 것이다

그래서 포트 연결을 해제 할때는
while문의 조건을 false로 만들어주고

        public void Stop_Read_Thread()
        {
            is_Continue_Read_Thread = false;
        }

해당 스레드가 완전히 종료될때까지 while문으로 붙잡아둔다
(아래의 코드는 MainForm에서 작성한 것이다)

                cls_Bill.Stop_Read_Thread();
                
                while (cls_Bill.read_Thread.IsAlive == true)
                {
                    ClassApp.Delay(5);
                }
                
                cls_Bill.read_Thread = null;

그 후에 스레드를 null로 만들어준다

'C# 개인 공부 기록용 > Memo' 카테고리의 다른 글

NuGet restore 오류 해결 방법  (2) 2023.03.09
윈폼 디자인 꾸미기  (0) 2022.11.22
Event 처리의 흐름  (0) 2022.08.24
UI 둥글게 만들기  (0) 2022.08.19
C# Spreadsheet 도구 상자에 추가하는 방법  (0) 2022.08.02