티스토리 뷰

목차

    반응형

    스레드풀 전체 소스를 소개합니다. 출처는 기억이 안 나는데, 아마도 스택 오버플로우일 겁니다.


    프로젝트 압축 파일

    C# 쓰레드풀 예제 프로젝트 - ThreadPoolExam.zip


    C# 쓰레드풀 소스 (Thread pool runnable example)[C# 쓰레드풀 소스 (Thread pool runnable example)]


    아래는 스레드풀 메인 클래스인데, Action을 이용해 랜덤한 스레드 시작과 종료 코드를 실행합니다.


    5번째 라인의 thread pool 클래스에서 실제 스레드 객체도 생성합니다.



    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    static void Main(string[] args)
    {
        using (var pool = new Pool(5)) // size
        {
            var random = new Random();
            Action<int> randomizer = (index =>
            {
                Console.WriteLine("{0}: Working on index {1}",
                    Thread.CurrentThread.Name, index);
     
                Thread.Sleep(random.Next(20400));
     
                Console.WriteLine("{0}: Ending {1}",
                    Thread.CurrentThread.Name, index);
            });
     
            for (var i = 0; i < 10++i)
            {
                var i1 = i;
                pool.QueueTask(() => randomizer(i1));
            }
        }
    }
    cs



    다음은 쓰레드풀 클래스의 생성자와 사용되는 변수 4개 입니다. 링크드리스트를 이용해 스레드 객체를 저장하죠.



    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // queue of worker thread pools ready to process actions
    private readonly LinkedList<Thread> _workers;
     
    // actions to be processed by worker threads
    private readonly LinkedList<Action> _tasks = new LinkedList<Action>();
     
    // set to true when disposing queue but there are still tasks pending
    private bool _disallowAdd; 
     
    // set to true when disposing queue and no more tasks are pending
    private bool _disposed;
    cs

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public Pool(int size)
    {
        this._workers = new LinkedList<Thread>();
     
        for (var i = 0; i < size; ++i)
        {
            var worker = new Thread(this.Worker)
            {
                Name = string.Concat("Worker ", i)
            };
     
            worker.Start();
            this._workers.AddLast(worker);
        }
    }
    cs



    아래는 스레드풀 핵심인 Worker 함수입니다.



    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
    private void Worker()
    {
        Action task = null;
     
        while (true// loop until thread pool is disposed
        {
            lock (this._tasks) // finding a task needs to be atomic
            {
                while (true// wait for our turn in _workers queue and an available task
                {
                    if (this._disposed)
                    {
                        return;
                    }
     
                    // we can only claim a task if its our turn (this worker thread is the first entry in _worker queue) and there is a task available
                    if (null != this._workers.First && object.ReferenceEquals(Thread.CurrentThread, this._workers.First.Value) && this._tasks.Count > 0
                    {
                        task = this._tasks.First.Value;
                        this._tasks.RemoveFirst();
                        this._workers.RemoveFirst();
                        Monitor.PulseAll(this._tasks); // pulse because current (First) worker changed (so that next available sleeping worker will pick up its task)
                        break// we found a task to process, break out from the above 'while (true)' loop
                    }
                    Monitor.Wait(this._tasks); // go to sleep, either not our turn or no task to process
                }
            }
     
            task(); // process the found task
     
            lock (this._tasks)
            {
                this._workers.AddLast(Thread.CurrentThread);
            }
            task = null;
        }
    }
    cs



    아래는 스레드풀 실행 결과인데 보시다시피, 랜덤한 실행이 됩니다.



    C# 스레드 풀 예제 소스[C# 쓰레드풀 소스 (Thread pool runnable example)]



    비동기 기능 구현 시 동기화 등 이슈가 많은데, 스레드풀 사용하면 편합니다.



    관련 글



    ⓒ written by vicddory

    반응형