본문 바로가기

hayee Study/코딩_c#

[C#] ConcurrentQueue, Queue

반응형

이전 프로젝트들부터 DB Query 를 처리하는 스레드에서 Dequeue 를 호출할 때마다 종종 string.empty 가 출력되서 예외로 빠진적이 있었다. string.emtpy 값을 넣은 적이 없는데 자주 발생하여 골머리를 앓고 있었다.

 

여러 스레드에서 Enqueue 메서드에 접근하기 때문에 이 상황이 발생하지 않을까? 란 생각이 들어서 임계영역을 걸어보기로 했다.

 

Enqueue, Dequeue 에 lock 을 걸어도 봤지만 그래도 발생하였기 때문에 다른 방법을 찾게 되었고,  MSDN 에서 Concurrentqueue 를 발견하게 되었다. 결국  Queue → ConcurrentQueue 로 변경하여 이 문제를 해결하였다.


◈ 설명

 

- Queue: 멀티스레드로 접근할 경우 간헐적으로 오류가 발생한다. 사용할 일이 있다면 크리티컬세션을 잘 선언하여 쓰도록 해야한다.

- Concurrentqueue: NET Framework 4.6 부터 지원하며 여러 스레드에서 동시에 접근해도 안전하다.


◈ 예제 소스 (1)

//ConcurrentQueue<string> m_Queue = new ConcurrentQueue<string>();
Queue<string> m_Queue = new Queue<string>();

// 멀티스레드 환경에서 문자열 Enqueue.
private void btnTest_Click(object sender, EventArgs e)
{ 
    m_th1 = new Thread(() => StartThread1());
    m_th1.Name = "test thread 1";
    m_th1.IsBackground = true;
    m_th1.Start();

    m_th2 = new Thread(() => StartThread2());
    m_th2.Name = "test thread 2";
    m_th2.IsBackground = true;
    m_th2.Start();
}

private void StartThread1()
{
    for (int i = 0; i < 100; i++)
    {
        string slog = string.Format("test1 string text {0}", i);
        m_Queue.Enqueue(slog);

        Thread.Sleep(10);
    }
}

private void StartThread2()
{
    for (int i = 100; i < 200; i++)
    {
        string slog = string.Format("test2 string text {0}", i);
        m_Queue.Enqueue(slog);

        Thread.Sleep(10);
    }
}

// Queue 안에 있는 문자열 출력.
private void btnTestD_Click(object sender, EventArgs e)
{
    for (int k = 0; k < m_Queue.Count; k++)
    {
        if (m_Queue.TryDequeue(out string result))
        {
            Trace.WriteLine("Success:" + result);
        }
        else
        {
            Trace.WriteLine("Fail result:" + result);
        }
    }
}

// 결과
//Success:test2 string text 140
//Success:				<<<< 중간중간 빈 문자열이 출력된 것을 확인할 수 있음.
//Success:test2 string text 141
//Success:test1 string text 41
//Success:test2 string text 142
//Success:test1 string text 42
//Success:test2 string text 143
//Success:test1 string text 43
//Success:test1 string text 44
//Success:test2 string text 144
//Success:test2 string text 145
//Success:test1 string text 45
//Success:test1 string text 46
//Success:test2 string text 146
//Success:test2 string text 147
//Success:				<<<<
//Success:test2 string text 148
//Success:				<<<<
//Success:test1 string text 49
//Success:test2 string text 149
//Success:test2 string text 150
//Success:test1 string text 50

 

- 동일한 소스에서 Queue→ ConcurrentQueue 로 바꾸어 테스트를 하면 빈 문자열이 출력되지 않는 것을 확인할 수 있다.

 

 

 

 

# 틀린 부분이 있다면 댓글 부탁드립니다. #

# 댓글 달아주시면 늦게라도 블로그 방문하도록 할게요! 감사합니다. #

728x90
반응형