본문 바로가기

C#

c# autoresetevent로 스레드 통제하기

autoresetevent에서 set과 waitone 명령어로 스레드의 동작을 재개/중지가 가능하다

set을 보내면 waitone 밑의 코드가 실행된다. 동시에 autoresetevent의 상태는 false가 되어서 set 명령어가 다시 실행되어야만 waitone 밑의 코드가 실행되게 되어있다.

이는 manualresetevent 객체와 다른점이다. manualresetevent는 set을 하면 manualresetevent의 상태는 true가 되고, 명시적으로 reset 명령어를 해 주어야만 manualresetevent의 상태는 false가 된다.

lock 명령어로 queue를 사용할 시 하나의 스레드만 접근 가능하도록 만든다.

main thread 또한 추가적으로 접근이 가능하기에 그렇다.

 

== 코드 ==

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
using System;
using System.Threading;
using System.Collections.Generic;
 
namespace TestMultiThreadLock
{
    class Program
    {
        
        static void Main(string[] args)
        {
            Traffic traffic = new Traffic();
            Thread v = new Thread(traffic.ProcessVertical);
            Thread h = new Thread(traffic.ProcessHorizontal);
            v.Start();
            h.Start();
 
            for (int i =0; i<30; i+=3)
            {
                traffic.AddVertical(new int[] { i, i + 1, i + 2 });
                traffic.AddHorizontal(new int[] { i, i + 1, i + 2 });
                Thread.Sleep(10);
            }
            Thread.Sleep(1000);
            traffic.Running = false;
            Console.ReadKey();
        }
 
 
 
    }
 
    class Traffic
    {
        private bool _running = true;
        
        private AutoResetEvent _evtVert = new AutoResetEvent(true);
        private AutoResetEvent _evtHoriz = new AutoResetEvent(false);
 
        private Queue<int> _Qvert = new Queue<int>();
        private Queue<int> _Qhoriz = new Queue<int>();
 
        public void ProcessVertical()
        {
            while (_running)
            {
                _evtVert.WaitOne();
 
                lock (_Qvert)
                {
                    while (_Qvert.Count > 0)
                    {
                        int val = _Qvert.Dequeue();
                        Console.WriteLine("Vertical : {0}", val);
                    }
                }
 
                _evtHoriz.Set();
            }
        }
 
        public void ProcessHorizontal()
        {
            while (_running)
            {
                _evtHoriz.WaitOne();
 
                lock (_Qhoriz)
                {
                    while (_Qhoriz.Count > 0)
                    {
                        int val = _Qhoriz.Dequeue();
                        Console.WriteLine("Horizontal : {0}", val);
                    }
                }
                _evtVert.Set();
            }
            Console.WriteLine("ProcessHorizontal : Done");
        }
 
 
        public bool Running { 
            get { return _running; }
            set { _running = value; }
        }
 
        public void AddVertical(int[] data)
        {
            lock (_Qvert)
            {
                foreach (var item in data)
                {
                    _Qvert.Enqueue(item);
                }
            }
        }
 
        public void AddHorizontal(int[] data)
        {
            lock (_Qhoriz)
            {
                foreach (var item in data)
                {
                    _Qhoriz.Enqueue(item);
                }
            }
        }
 
    }
 
}
 
cs