티스토리 뷰
목차
반응형
스레드풀 전체 소스를 소개합니다. 출처는 기억이 안 나는데, 아마도 스택 오버플로우일 겁니다.
프로젝트 압축 파일
C# 쓰레드풀 예제 프로젝트 - ThreadPoolExam.zip
[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(20, 400)); 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# 쓰레드풀 소스 (Thread pool runnable example)]
비동기 기능 구현 시 동기화 등 이슈가 많은데, 스레드풀 사용하면 편합니다.
관련 글
- C# 비동기 Async, 소켓 서버, 함수 소스 (Socket network)
- C# 비동기 프로세스 제어 소스, async task process
- C# Lambda 예제, if else 람다 축약 방법 (Action 델리게이트)
ⓒ written by vicddory
반응형