반응형
이전 프로젝트들부터 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
반응형
'hayee Study > 코딩_c#' 카테고리의 다른 글
[C#] AutoResetEvent, ManualResetEvent 에 대하여 (0) | 2023.10.08 |
---|---|
[C#] show, showDialog (모달리스와 모달 차이점) (2) | 2023.10.03 |
[C#] ProgressBar 사용법. (+ 색상 변경하기) (5) | 2023.10.02 |
[C#] 작업스케줄러 (2) | 2023.10.02 |
[C#] ? 연산자 (조건부 연산자) (0) | 2023.09.18 |