【发布时间】:2017-04-07 23:25:48
【问题描述】:
我一直在努力寻找一个简单的自定义线程池,但找不到,所以写了一个快速穷人的线程池。
问题:
是否有任何 .NET 类可以做到这一点? (经过多次尝试都找不到它,只有博客文章上的自定义实现比这复杂得多!)。
当任务进入时,最好通过轮询或启动线程池上的操作来消耗线程?
代码
public class WorkerQueue : IWorkerQueue
{
private readonly Queue<WorkItem> _items = new Queue<WorkItem>();
private int _max = 2; // Would be configurable
private int _running;
private Stopwatch _stopwatch;
public WorkerQueue()
{
_stopwatch = new Stopwatch();
_stopwatch.Start();
}
public void Add(WorkItem workItem)
{
lock (_items)
{
if (_running >= _max)
{
Log($"Queuing Item {workItem.Name} - _running >= _max");
_items.Enqueue(workItem);
return;
}
_running++;
Log($"Running Item {workItem.Name} - _running = {_running}");
var task = Task.Run(workItem.Action);
task.ContinueWith(t => OnActionCompleted(workItem.Name));
}
}
private void Log(string msg)
{
Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} @ {_stopwatch.ElapsedMilliseconds}ms : {msg}");
}
private void OnActionCompleted(string obj)
{
Log($"OnActionCompleted {obj}");
WorkItem item = null;
lock (_items)
{
if (_items.Count > 0)
item = _items.Dequeue();
else
_running--;
}
if (item != null)
{
// Potential Stack Overflow if big queue builds up?
// Probably should be a while loop rather than recursion?
Log($"Running Next Item {item.Name}");
item.Action();
OnActionCompleted(item.Name);
}
else
{
Log($"Sleeping. _running = {_running}");
}
}
}
还有一个测试:
[Fact]
public void Test()
{
var sb = new StringBuilder();
Console.SetOut(new StringWriter(sb));
var resetEvent = new ManualResetEventSlim();
AddItem("A", 100);
AddItem("B", 250);
AddItem("C", 100);
AddItem("D", 100);
AddItem("E", 100);
AddItem("G", 100, () =>
{
Thread.Sleep(250);
resetEvent.Set();
});
resetEvent.Wait(2500);
Assert.True(resetEvent.IsSet);
_output.WriteLine("");
_output.WriteLine("------------------ Test Finished ------------------");
_output.WriteLine("------------------ Console Out ------------------");
_output.WriteLine("");
_output.WriteLine(sb.ToString());
}
并得到正确(或足够正确)的输出
Thread 14 @ 8ms : Running Item A - _running = 1
Thread 14 @ 8ms : Running Item B - _running = 2
Thread 14 @ 8ms : Queuing Item C - _running >= _max
Thread 14 @ 8ms : Queuing Item D - _running >= _max
Thread 14 @ 8ms : Queuing Item E - _running >= _max
Thread 14 @ 8ms : Queuing Item G - _running >= _max
Thread 21 @ 110ms : OnActionCompleted A
Thread 21 @ 110ms : Running Next Item C
Thread 21 @ 211ms : OnActionCompleted C
Thread 21 @ 211ms : Running Next Item D
Thread 20 @ 260ms : OnActionCompleted B
Thread 20 @ 260ms : Running Next Item E
Thread 21 @ 311ms : OnActionCompleted D
Thread 21 @ 311ms : Running Next Item G
Thread 20 @ 360ms : OnActionCompleted E
Thread 20 @ 360ms : Sleeping. _running = 1
Thread 21 @ 662ms : OnActionCompleted G
Thread 21 @ 662ms : Sleeping. _running = 0
【问题讨论】:
-
我投票结束这个问题,因为它应该属于 codereview.stackexchange.com 站点
-
@SergeyBerezovskiy 将问题改为询问 .NET 框架中是否已有可用的东西
-
Task 是 .NETCore 中的新线程,它通过线程池进行管理。
标签: c# multithreading threadpool