Skip to content

Instantly share code, notes, and snippets.

@edward-hsu-1994
Last active October 27, 2020 12:03
Show Gist options
  • Save edward-hsu-1994/b6b286a2ce8bfd02013ab05ef40c728d to your computer and use it in GitHub Desktop.
Save edward-hsu-1994/b6b286a2ce8bfd02013ab05ef40c728d to your computer and use it in GitHub Desktop.
Thread搭配Queue實現多Worker任務分發
/**
* Author: XuPeiYao
* License: MIT
* Summary: Thread搭配Queue實現多Worker任務分發
*/
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
using System.Threading;
namespace SimpleQueueExample
{
/// <summary>
/// 工作的內容包裝類別
/// </summary>
class Job
{
public string Something { get; set; }
}
class Program
{
static void Main(string[] args)
{
// 測試工作數量
int jobCount = 100;
// Worker數量
int workerCount = 3;
// 建立測試工作項目
ConcurrentQueue<Job> jobs = new ConcurrentQueue<Job>(
Enumerable.Range(0, jobCount).Select(x => new Job() { Something = "Job_" + x.ToString() })
);
// 計時器,計算總耗時
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
// 建立倒數事件
using (CountdownEvent counter = new CountdownEvent(workerCount))
{
// 建立Worker
for (int i = 0; i < workerCount; i++)
{
// 利用Tuple傳遞倒數事件以及工作Queue(可自己建立一個類別去包裝)
ThreadPool.QueueUserWorkItem(Runner, (counter, jobs));
}
// 等候倒數至0的信號
counter.Wait();
}
stopwatch.Stop();
Console.WriteLine("任務結束!");
Console.WriteLine($"總耗時: {stopwatch.Elapsed}");
}
static void Runner(object status)
{
// 用來識別Thread用的ID而已
Guid runnerId = Guid.NewGuid();
// 自status取出外部傳遞進來的Counter與工作Queue
var inputData = ((CountdownEvent counter, ConcurrentQueue<Job> jobs))status;
// 循環自Queue中嘗試取出工作,無工作時跳脫
while (inputData.jobs.TryDequeue(out Job jobForThisThread))
{
// 執行工作內容
Console.WriteLine(runnerId + ": " + jobForThisThread.Something + " - START");
Thread.Sleep(1000);
Console.WriteLine(runnerId + ": " + jobForThisThread.Something + " - FINSH");
}
// 針對倒數事件送出倒數信號
inputData.counter.Signal();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment