본문 바로가기
  • AI (Artificial Intelligence)
Programming/C, C++

[C#] Queue, Thread, AutoReset

by 로샤스 2014. 3. 31.

 

운영체제

Windows7

최초 작성일 2013/12/10

프로그램 및 버전

VisualStudio2010/.Net FW 4.0

마지막 수정 작성일 -

※ 주의사항

-

 

1. 작업개요

이 포스팅 역시 제가 나중에 써먹기 위해서 작성하는 글 입니다. 

이 포스팅에서 다뤄지는 내용은 Queue, Thread, AutoReset 입니다. 

 

시나리오는 DB에 저장되는 데이터가 꾸준하게 들어옵니다.(누군가가 팍팍 던져 주겠지요.) 

그것을 받아서 DB에 입력을 해야하는데 들어오는 데이터량이 많아 받고쓰고받고쓰고 하면 속도가 어마어마하게 걸릴 것 입니다. 

그래서 들어오는 데이터는 Queue에 저장하고 다른 Thread로 그 Queue에 담긴 데이터를 DB에 입력하려고 합니다. 

지금은 DB에 입력하는 부분이지만 시리얼통신, TCP, UDP통신에서도 이같은 방법으로 데이터를 받고 처리할 수 있습니다. 

 

2. 작업내용

1) Queue, Thead, AutoReset 선언

소스 및 이미지

line1 :        Queue<String> orderDBQueue = new Queue<String>();
line2 :        Thread orderDBQueueThread = null;//orderDBQueue 처리 스레드
line3 :        bool isRunOrderDBQueueThread = true;
line4 :        AutoResetEvent orderDBQueueThreadEvent = new AutoResetEvent(false);

설명

보시는 봐와 같이 line1에서는 String을 담을 수 있는 큐를 생성하였습니다. 예시로 String을 하였지만 int라든지 만일 통신에서의 

패킷을 담을 것이면 해당 패킷의 DataClass를 넣으셔도 됩니다. 

 

line2에서는 데이터 처리를 하는 스레드 입니다. line3는 스레드 처리 부분에서 사용이 되는데요. 아래 2)에서 스레드를 생성하면 

 

isRunOrderDBQueueThread값을 true로 바꿔 4)에서 큐에 담긴 데이터를 처리할 수 있게 합니다. 

 

StopThread()에서 다시 false값으로 변경하며, StopThread()가 호출된 시점까지의 데이터만 깔끔하게 처리하고 끝날 수 있게 

도와줍니다. 

 

line4의 AutoResetEvent는 대기중인 스레드에 이벤트가 발생하였음을 알려주며, 3)에서 데이터를 큐에 넣고 스레드를 활성화 

할 수 있게 orderDBQueueThreadEvent.set() 을 호출합니다. 4)에서 큐에 데이터가 없으면  

orderDBQueueThreadEvent.WaitOne()을 호출하여 '얼음'을 만들어주고 큐에 데이터가 들어가면 '땡' 해주는 것 입니다.

 

2) 스레드 생성 소멸 함수 만들기

소스 및 이미지

 //생성 함수

        private void StartThread()
        {
            orderDBQueue.Clear();
            if (orderDBQueueThread == null)
            {
                orderDBQueueThread = new Thread(new ThreadStart(DBInsertOrderData));
                orderDBQueueThread.Priority = ThreadPriority.Normal;
                isRunOrderDBQueueThread = true;
                orderDBQueueThread.Start();
            }
        }
 
//소멸 함수
        private void StopThread()
        {
            if (orderDBQueueThread != null)
            {
                isRunOrderDBQueueThread = false;
                orderDBQueueThreadEvent.Set();
                orderDBQueueThread.Abort();
                orderDBQueueThread = null;
            }
        }
 

설명

스레드는 스레드를 생성하는 StartThread()와 이를 다시 소멸하는 StopThread()함수를 만들어 관리하는 것이 편리합니다. 

프로그램 생성자에 StartThread()를 넣어 Thread가 같이 생성하도록 합니다. 

그리고 프로그램이 종료되는 시점에 StopThread를 이용하여 프로그램종료와 동시에 해당 스레드도 소멸되게 합니다. 

만일 생성한 스레드를 소멸시키지 않는다면... 영원히 살아있겠지요 

 

3) Queue에 데이터 넣기

소스 및 이미지

 

        public void InsertErrQueue(String str)
        {
            lock (orderDBQueue)
            {
                orderDBQueue.Enqueue(str);
            }
            orderDBQueueThreadEvent.Set();
        }
 

설명

위 함수는 외부로 노출하여 DB에 넣을 데이터를 넘겨받는 부분입니다. 이부분에서 저는 특별한 작업없이 바로 큐에 넣습니다. 

여기서 보시면 큐에 lock을 걸고 Enqueue를 하게 되는데요. 그 이유는 잘못하면 Dequeue하는 작업과 꼬이게 되어 병목현상? 

이 발생할 수 있어 lock을 걸고 Enqueue를 합니다. 물론 Dequeue할때도 lock을 걸고 진행합니다. 

  

  

4) Thread처리 함수

소스 및 이미지

        private void DBInsertOrderData()
        {
            while (isRunOrderDBQueueThread)
            {
                try
                {
                    int queueCount = 0;
                    lock (orderDBQueue)
                    {
                        queueCount = orderDBQueue.Count;
                    }
 
                    if (queueCount <= 0)
                    {
                        orderDBQueueThreadEvent.WaitOne();
                    }
                    else
                    {
                        String str = string.Empty;
                        lock (orderDBQueue)
                        {
                            str = orderDBQueue.Dequeue();
                        }
                        InsertDBData(str);
                    }
                }
                catch (Exception err)
                {
                    Debug.WriteLine(string.Format("***[{0}]FancINFOMng-INFOMng.cs-DBInsertOrderData() : 오류발생({1})"
                    DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), err.Message));
                }
            }
        }

설명

이제 DB에 넣는 스레드에서 처리하는 부분입니다. 위에서 언급하였던 isRunOrderDBQueueThread도 보이구요.

Dequeue할때 lock하는 것도 보입니다.

소스를 설명하자면 isRunOrderDBQueueThread를 통해 스레드가 시작되었다는 것을 알고 while문이 돕니다.

그리고 lock을 걸어 큐카운트를 확인하여 큐에 데이터가 없으면 orderDBQueueThreadEvent.WaitOne();

을 호출하여 '얼음'을 만들어주고 만일 데이터가 있으면 lock을 걸고 Dequeue를 하여 DB에 insert해주는 InsertDBData함수를

호출합니다.

 

3. 작업결과

-

※ 참고 사이트

-

위 사이트를 참고 하였습니다.

 

 

 
 

 

 

출처 : http://happytomorrow.net/90186225934

 

 

 

 

 

 

'Programming > C, C++' 카테고리의 다른 글

[C언어]strcmp함수  (1) 2014.07.18
다시쓰는 C언어 강좌] 079 - 열거형 - enum  (0) 2014.07.18
비동기 입출력 프로그래밍  (0) 2014.04.16
Chapter 1. C++ 시작하기 pdf 파일  (0) 2014.03.31

댓글