C#。是否有用于自定义线程池的.NET类
我一直试图找到一个简单的自定义线程池有一段时间了,但找不到,所以写了一个快速的穷人线程池 问题:C#。是否有用于自定义线程池的.NET类,c#,multithreading,threadpool,C#,Multithreading,Threadpool,我一直试图找到一个简单的自定义线程池有一段时间了,但找不到,所以写了一个快速的穷人线程池 问题: 是否有任何.NET类已经可以这样做了?(在多次尝试找到一个后,都找不到它,只有博客帖子上的自定义实现比这个复杂得多!) 当任务进入时,最好使用线程池上的轮询或启动操作来使用线程 您可以查看,它有几个任务调度器。具体来说,WorkStealingTaskScheduler 我记得我曾经对它进行过测试,托管世界中没有任何东西可以与.NET自己的线程池相比,至少在没有不安全代码的情况下是如此。NET的库存
WorkStealingTaskScheduler
我记得我曾经对它进行过测试,托管世界中没有任何东西可以与.NET自己的线程池相比,至少在没有不安全代码的情况下是如此。NET的库存线程池有很多优化,我清楚地记得其中一个优化是在等待前处理一个工作项之后,积极地旋转工作项
好的一面是,您可以非常接近它,但是模仿ThreadPool
所做的是一项相当了不起的壮举。也就是说,如果你想这样做的话。我不想使用默认线程池的原因之一是,它的策略是在min.threads之后缓慢创建线程,但简单地增加min.threads通常就足够了
问题是,除非您使用的是TPL和,否则您可以提供自己的任务调度器,因为没有库存线程池接口,通常其他任何东西,尤其是遗留代码,都不会占用您的自定义线程池。不幸的是,
ThreadPool
是一个静态类这一事实进一步阻碍了其他线程池的使用。您可以看看,它有几个任务调度器。具体来说,WorkStealingTaskScheduler
我记得我曾经对它进行过测试,托管世界中没有任何东西可以与.NET自己的线程池相比,至少在没有不安全代码的情况下是如此。NET的库存线程池有很多优化,我清楚地记得其中一个优化是在等待前处理一个工作项之后,积极地旋转工作项
好的一面是,您可以非常接近它,但是模仿ThreadPool
所做的是一项相当了不起的壮举。也就是说,如果你想这样做的话。我不想使用默认线程池的原因之一是,它的策略是在min.threads之后缓慢创建线程,但简单地增加min.threads通常就足够了
问题是,除非您使用的是TPL和,否则您可以提供自己的任务调度器,因为没有库存线程池接口,通常其他任何东西,尤其是遗留代码,都不会占用您的自定义线程池。不幸的是,
ThreadPool
是一个静态类,这一事实进一步阻碍了其他线程池的使用。我投票结束这个问题,因为它应该属于site@SergeyBerezovskiy将问题更改为询问中是否已有可用的内容,NET framework alreadyTask是.NETCore中的新线程,它通过一个线程池进行管理。我投票将此问题作为主题外的问题结束,因为它应该属于site@SergeyBerezovskiy将问题更改为询问中是否已有可用的内容,NET framework alreadyTask是.NETCore中的新线程,它通过线程池进行管理。我不想覆盖默认的线程池,而是寻找一个单独的线程池,我可以使用它,并指定一次可以运行多少线程。我明白了,你读了我的第一段吗?WorkStealingTaskScheduler
可能是最接近微软自己在托管代码中实现线程池的工具。但请参见同一项目中的LimitedConcurrencyLevel TaskScheduler
。我不是要覆盖默认的线程池,而是一个单独的线程池,我可以对其进行设置,并指定一次可以运行多少线程池。我明白了,你读了我的第一段了吗?WorkStealingTaskScheduler
可能是最接近微软自己在托管代码中实现线程池的工具。但请参见同一项目中的limitedconcurrensionleveltaskscheduler
。
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