티스토리 뷰

C#/C# 강좌 Winform

Doridori C# 강의) 27.Thread Stop

꼬꼬마도리도리 2018. 12. 30. 21:51

======================================================

안녕하세요 Doridori 입니다. 


이번 강의는 지난 시간에 했던 Thread에 이어서 Thread의 종료에 대한 강의 입니다. 


지난 강의에 이어서 Thread Stop에 대한 내용을 요청 하시는 분이 몇분 계셔서 (아직 많은 분들일 제 강의를 보시지 않으 십니다. ㅜㅠ 으헝헝)


빨리 준비해 보았습니다. 


올해가 끝나기 전에 올릴려고 조금 노력 했습니다. ^^;;


알찬 내용이 되셨으면 좋겠습니다.

======================================================


Thread Stop


Source UI) (지난 강의 마지막 완료 Source를 받아서 사용 하시면 됩니다.)

Soruce 전체) Study_27_Thread Stop.zip

교재) 27강 Thread Stop.pdf










이번강의는 Thread Stop에 대한 강의 입니다. 


지난 강의에서 바로 연결 되는 내용이므로 지난 강의 전체 Source를 받아서 시작 하시면 될것 같습니다. 


Thread의 경우 사용 하는것보다 자원의 회수가 더 중요하다고 말씀 드렸는데 제가 일하는 곳의 경우 공장 쪽이다 보니 한번 PC를 넣으면 이녀석이 한달, 1년, 5년 내내 쉬지 않고 일하게 됩니다. (물론 장비를 청소하더나 보수하는 시간에는 쉬기는 합니다만. . . )


어쨋든 거의 쉬지 않고 계속 돌아가야 하기 때문에 Thread 관리가 제대로 되지 않을 경우 PC 부하가 조금씩 쌓이게 되는데 처음에는 티가 나지 않다가 점점 쌓이면 컴퓨터가 느려지는 현상이 발생하고 신호를 놓치는 현상이 생기면서 PC가 멈추거나 프로램이 오작동을 하는 상황이 발생하게 됩니다. 


24시간 계속 돌아가야 하는데 이런 문제가 발생 하게 되면 매우 심각한 타격을 받게 됩니다. 


(불려가서 욕을 엄청 먹어야 해요 ... ㅜㅠ 손해가 얼마고 . . . 뭔 손해가 내 연봉의 몇배는 뛰어넘는데 이거 몸팔아서 갚아야 하나... 싶기도 합니다.)


요는 자원의 관리라던지 효율이라던지 하는게 쉽게 볼일은 아닌것 같습니다. ^^;;


그렇다고 여기에다가 목숨을 걸어라 라는 느낌은 아니고 그냥 너무 아무것도 안하고 넘어가지 말고 신경 쓸 부분만 신경 쓰고 넘어가면 될것 같습니다. 


(문제가 발생 하면 고치면 되지요~! 개인적으로 개발자가 너무 완벽하게 하려고 하면 이상한데 꽃혀서 프로그램이 산으로 간다고 생각 합니다. 실수도 할수있고 하니 테스트 하는 분들도 뽑아서 테스트도 해보고 시범운영 기간도 가져보고 하는게 아니겠습니까. =0=b)



지난 번에 하지 못했던 함수들에 대한 설명을 하기 위해서 지난번강의에서 설명했던 부분은 회색 처리 했했습니다. (지난번 강의도 설명하지 않은 부분은 회색 처리로 변경 했습니다.)


Thread를 중단 시키는 방법에 대한 내용을 3가지 정도로 정리해 보았습니다. 


요지는 Thread로 호출한 함수를 종료 시키는 것!! 이라고 보시면 될것 같습니다. 




의)





Source)


지난 번과 중복되는것 같기는 하지만 추가한 내용들이 있으니 전체 Source를 올리도록 하겠습니다. 


Thread를 Stop 시키는 부분들과 호출한 Form들을 확인 하기 위해서 Form을 호출 할 때 List에 입력 하는 부분, 프로그램 종료시 Form Closing Event 등을 추가 하였습니다. 



Main Form )


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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 _26_Thread
{
    public partial class Form1 : Form
    {
        private enum enumPlayer
        {
            아이린,
            슬기,
            웬디,
            조이,
            예리,
        }
 
        int _locationX = 0;
        int _locationY = 0;
 
        List<Play> lPlay = new List<Play>();
 
        public Form1()
        {
            InitializeComponent();
 
            _locationX = this.Location.X;
            _locationY = this.Location.Y;
        }
        
        private void Form1_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
        {
            foreach (Play oPlayForm in lPlay)
            {
                oPlayForm.ThreadAbort();  // 프로그램 종료 시점이라서 강제로 Thread를 해제
            }
        }
 
        private void btnStart_Click(object sender, EventArgs e)
        {
            _locationX = this.Location.X + this.Size.Width;
            _locationY = this.Location.Y;
 
            for (int i = 0; i < numPlayerCount.Value; i++)
            {
                Play pl = new Play(((enumPlayer)i).ToString());
                pl.Location = new Point(_locationX, _locationY + pl.Height * i);
                pl.eventdelMessage += Pl_eventdelMessage;
 
                pl.Show();
 
                pl.fThreadStart();
 
                lPlay.Add(pl);
            }
 
           
        }
 
        private int Pl_eventdelMessage(object sender, string strResult)
        {
            if (this.InvokeRequired)   // 요청 한 Thread가 현재 Main Thread 있는 Contorl을 엑세스 할 수 있는지 확인
            {
 
                this.Invoke(new Action(delegate ()
                {
 
                    Play oPlayerForm = sender as Play;
 
                    lboxResult.Items.Add(string.Format("Player : {0}, Text : {1}", oPlayerForm.StrPlayerName, strResult));
                }));
 
            }
 
            return 0;
        }
    }
}
 
cs




Sub Form (Play))


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace _26_Thread
{
    public partial class Play : Form
    {
        public delegate int delMessage(object sender, string strResult);  // delgate 선언
        public event delMessage eventdelMessage;
 
 
        string _strPlayerName = string.Empty;
        public string StrPlayerName { get => _strPlayerName; set => _strPlayerName = value; }
 
        Thread _thread = null;
 
        bool _bThreadStop = false;  // Thread Stop을 위한 Flag 생성
 
        public Play()
        {
            InitializeComponent();
        }
 
        public Play(string strPlayerName)
        {
            InitializeComponent();
 
            lblPlayerName.Text = StrPlayerName = strPlayerName;
        }
 
        public void fThreadStart()
        {
            //_thread = new Thread(new ThreadStart(Run));   // ThreadStart 델리게이트 타입 객체를 생성 후 함수를 넘김
 
            _thread = new Thread(Run);   // 컴파일러에서 델리게이트 객체를 추론해서 생성 후 생성 후 함수를 넘김 (new ThreadStart 생략)
 
            //_thread = new Thread(delegate () { Run(); });   // 익명메소드를 사용하여 생성 후 함수를 넘김
 
            _thread.Start();
        }
 
 
        private void Run()
        {
            // UI Control이 자신이 만들어진 Thread가 아닌 다른 Thread에서 접근할 경우 Cross Thread가 발생
            //CheckForIllegalCrossThreadCalls = false;   // Thread 충돌에 대한 예외 처리를 무시 (Cross Thread 무시)
 
            try
            {
 
                int ivar = 0;
 
                Random rd = new Random();
 
                while (pbarPlayer.Value < 100  && !_bThreadStop)
                {
                    if (this.InvokeRequired)   // 요청 한 Thread가 현재 Main Thread 있는 Contorl을 엑세스 할 수 있는지 확인
                    {
                        this.Invoke(new Action(delegate ()
                        {
                            //함수값
                            ivar = rd.Next(1, 11);
                            //pbarPlayer.Value = ()
                            if (pbarPlayer.Value + ivar > 100)
                            {
                                pbarPlayer.Value = 100;
                            }
                            else
                            {
                                pbarPlayer.Value = pbarPlayer.Value + ivar;
                            }
 
                            lblProcess.Text = string.Format("진행 상황 표시 : {0}%", pbarPlayer.Value);
 
                            this.Refresh();
 
 
                        }));
 
                        Thread.Sleep(300);
                    }
                }
 
                if (_bThreadStop)
                {
                    eventdelMessage(this, "중도 포기...(Thread Stop)");
                }
                else
                {
                    eventdelMessage(this, "완주!! (Thread Complete)");
                }
            }
 
            catch (ThreadInterruptedException exInterrupt)
            {
                exInterrupt.ToString();
            }
            catch (Exception ex)
            {
                ex.ToString();
            }
        }
    
        
        public void ThreadAbort()
        {
            if (_thread.IsAlive)   // Thread가 동작 중 일 경우 
            {
                _thread.Abort();  // Thred를 강제 종료
            }
        }
 
 
        public void ThreadJoin()
        {
            if (_thread.IsAlive)
            {
                bool bThreadEnd = _thread.Join(3000);
            }
        }
 
 
        public void ThreadInterrupt()
        {
            if (_thread.IsAlive)
            {
                _thread.Interrupt();
            }
        }
 
 
        private void btnStop_Click(object sender, EventArgs e)
        {
            //hreadInterrupt();
            if (_thread.IsAlive)
            {
                _bThreadStop = true;
            }
        }
 
    }
}
 
cs



댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함