첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

작업 조건이 아래와 같은 경우를 위한 비동기 순차 처리 코드이다.

  • 1번 쓰기 작업 완료 후 1번 읽기 작업을 할 수 있고 2번 쓰기 작업 완료 후 2번 읽기 작업을 할 수 있다.
  • 1번 쓰기 작업 완료 후 2번 쓰기 작업을 할 수 있고 2번 쓰기 작업 완료 후 3번 쓰기 작업을 할 수 있다.
  • 1번 읽기 작업 완료 후 2번 읽기 작업을 할 수 있고 2번 읽기 작업 완료 후 3번 읽기 작업을 할 수 있다.
  • 쓰기 작업은 동시에 50개까지 할 수 있다.
  • 읽기 작업은 동시에 50개까지 할 수 있다.
  • 모든 쓰기/읽기 작업이 완료될 때까지 프로그램 종료를 보류한다.

 

728x90

 

▶ Program.cs

using System;
using System.Collections.Generic;
using System.Threading;

namespace TestProject
{
    /// <summary>
    /// 프로그램
    /// </summary>
    class Program
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 난수 발생기
        /// </summary>
        /// <remarks>작업 시간을 임의로 설정하기 위한 것이다.</remarks>
        private static Random _random = null;

        /// <summary>
        /// 쓰기 자동 리셋 이벤트 딕셔너리
        /// </summary>
        /// <remarks>첫번째 쓰기 작업이 끝나기 전에 두번째 쓰기 작업이 시작되는 것을 방지하기 위한 것이다.</remarks>
        private static Dictionary<int, AutoResetEvent> _writeAutoResetEventDictionary = null;

        /// <summary>
        /// 읽기 자동 리셋 이벤트 딕셔너리
        /// </summary>
        /// <remarks>첫번째 읽기 작업이 끝나기 전에 두번째 읽기 작업이 시작되는 것을 방지하기 위한 것이다.</remarks>
        private static Dictionary<int, AutoResetEvent> _readAutoResetEventDictionary = null;

        /// <summary>
        /// 카운트 다운 이벤트
        /// </summary>
        /// <remarks>모든 쓰기/읽기 작업이 완료될 때까지 대기하기 위한 것이다.</remarks>
        private static CountdownEvent _countdownEvent = null;

        /// <summary>
        /// 쓰기 세마포어
        /// </summary>
        /// <remarks>동시에 처리 가능한 쓰기 작업 수를 제한하기 위한 것이다.</remarks>
        private static SemaphoreSlim _writeSemaphore = new SemaphoreSlim(50);

        /// <summary>
        /// 읽기 세마포어
        /// </summary>
        /// <remarks>동시에 처리 가능한 읽기 작업 수를 제한하기 위한 것이다.</remarks>
        private static SemaphoreSlim _readSemaphore = new SemaphoreSlim(50);

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region 데이터 쓰기 - WriteData(parameter)

        /// <summary>
        /// 데이터 쓰기
        /// </summary>
        /// <param name="parameter">매개 변수</param>
        private static void WriteData(object parameter)
        {
            int i = (int)parameter;

            try
            {
                if(i > 0)
                {
                    _writeAutoResetEventDictionary[i - 1].WaitOne();
                }

                // 임의 작업을 한 것으로 가정한다.
                Thread.Sleep(_random.Next(30, 100));

                Console.WriteLine(i.ToString() + "번 쓰기 작업을 완료했습니다.");

                _readSemaphore.Wait();

                Thread thread = new Thread(new ParameterizedThreadStart(ReadData));

                thread.Start(i);
            }
            finally
            {
                _writeAutoResetEventDictionary[i].Set();

                _writeSemaphore.Release();
            }
        }

        #endregion
        #region 데이터 읽기 - ReadData(Parameter)

        /// <summary>
        /// 데이터 읽기
        /// </summary>
        /// <param name="parameter">매개 변수</param>
        private static void ReadData(object parameter)
        {
            int i = (int)parameter;

            try
            {
                if(i > 0)
                {
                    _readAutoResetEventDictionary[i - 1].WaitOne();
                }

                Thread.Sleep(_random.Next(30, 100));

                Console.WriteLine(i.ToString() + " 차트 읽기 작업을 완료했습니다.");
            }
            finally
            {
                _readAutoResetEventDictionary[i].Set();

                _countdownEvent.Signal();

                _readSemaphore.Release();
            }
        }

        #endregion
        #region 프로그램 시작하기 - Main()

        /// <summary>
        /// 프로그램 시작하기
        /// </summary>
        private static void Main()
        {
            _random = new Random();

            // 처리할 작업 수를 설정한다.
            int threadCount = 100;

            // 작업을 순차적으로 처리하기 위한 쓰기/읽기 동기 객체 딕셔너리를 초기화 한다.
            _writeAutoResetEventDictionary = new Dictionary<int, AutoResetEvent>();
            _readAutoResetEventDictionary  = new Dictionary<int, AutoResetEvent>();

            for(int i = 0; i < threadCount; i++)
            {
                _writeAutoResetEventDictionary.Add(i, new AutoResetEvent(false));

                _readAutoResetEventDictionary.Add(i, new AutoResetEvent(false));
            }

            // 모든 쓰기/읽기 작업이 완료될 때까지 대기하기 위한 동기 객체를 초기화 한다.
            _countdownEvent = new CountdownEvent(threadCount);

            // 작업을 처리한다.
            for(int i = 0; i < threadCount; i++)
            {
                Console.WriteLine(i.ToString() + "번 작업을 시작합니다.");

                _writeSemaphore.Wait();

                Thread writeThread = new Thread(new ParameterizedThreadStart(WriteData));

                writeThread.Start(i);

                Thread.Sleep(200);
            }

            // 모든 쓰기/읽기 작업이 완료될 때까지 대기한다.
            _countdownEvent.Wait();

            Console.WriteLine("작업을 완료했습니다.");
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요