multithreading - C# .Is there a .NET class for custom thread pools -
i have been trying find simple custom thread pool while, , couldn't find one, wrote quick poor man's thread pool.
questions:
is there .net class can already? (couldn't find after numerous attempts find one, custom implementations on blog posts lot more complex this!).
better consume threads polling or kicking off actions on thread pool when , tasks come in? <1k tasks / day. running aspnetcore site on kestrel
code
public class workerqueue : iworkerqueue { private readonly queue<workitem> _items = new queue<workitem>(); private int _max = 2; // 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? // should while loop rather recursion? log($"running next item {item.name}"); item.action(); onactioncompleted(item.name); } else { log($"sleeping. _running = {_running}"); } } } and test:
[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()); } and output correct (or correct enough)
thread 14 @ 8ms : running item - _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 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
you can take @ parallel extensions extras project, has several task schedulers. specifically, workstealingtaskscheduler.
i remember having tested it, , nothing in managed world compares .net's own thread pool, @ least without unsafe code. .net's stock thread pool has lot of optimizations under hood, 1 remember spinning aggressively work items after processing 1 work item before waiting.
on bright side, can close it, emulating threadpool quite feat. is, if want so. 1 of reasons i'd not use default thread pool due policy creating threads after min. threads, increasing min. threads enough.
the thing is, unless you're using tpl and can provide own task scheduler, typically nothing else, legacy code, going pick custom thread pool there no stock thread pool interface. unfortunately, fact threadpool static class further discourages usage of other thread pools.
Comments
Post a Comment