C# 使用一组有限的线程定期启动类似的任务
我以前也问过类似的问题,但经过深思熟虑,以及那些回答我的人的实施,我发现我的方法可能不正确 当我执行上一个问题的解决方案时,出现了以下测试结果:C# 使用一组有限的线程定期启动类似的任务,c#,multithreading,visual-studio-2010,timer,threadpool,C#,Multithreading,Visual Studio 2010,Timer,Threadpool,我以前也问过类似的问题,但经过深思熟虑,以及那些回答我的人的实施,我发现我的方法可能不正确 当我执行上一个问题的解决方案时,出现了以下测试结果: 当我“模拟”线程池中多个线程上并发运行的多个任务时(例如,通过使线程在1到20秒的随机时间睡眠),那么模型似乎工作正常。我将系统设置为每1秒轮询一次,以查看是否可以生成另一个线程,并且一切都似乎正常。长时间运行(休眠)的线程将在稍后完成,并且线程将在整个位置启动和终止。如果我碰巧用完了线程(我将其设置为生成的线程不超过10个),它将坐在那里等待一个线程
Semaphore concurrentThreadsEnforcer = new Semaphore(value1, value2);
然后,启动的每个线程将调用:
concurrentThreadsEnforcer.WaitOne();
这将从信号量中获取一个插槽并将其提供给新线程,或者阻止新线程,直到有一个插槽可用为止
每当你的新线程完成它的工作,他(我喜欢个性化)必须打电话,原因很明显:
concurrentThreadsEnforcer.Release().
现在,关于构造函数,第二个参数相当简单:说明在任何给定时间有多少并发线程可以访问资源
第一个参数有点棘手。第二个参数和第一个参数之间的差异将说明为调用线程保留了多少个信号量插槽。也就是说,所有新生成的线程都将访问第一个参数所述的插槽数量,其余线程将访问到second参数的值将保留给创建信号量的原始线程(调用线程)
在您的情况下,对于最多10个线程,您将使用:
... = new Semaphore(10, 10);
既然我已经发布了一个故事,让我来嘲弄一下更多的细节
我将在新线程中这样做:
bool aquired = false;
try
{
aquired = concurrentThreadsEnforcer.WaitOne();
// Do some work here
} // Optional catch statements
finally
{
if (aquired)
concurrentThreadsEnforcer.Release();;
}
我会结合使用
BlockingCollection
和Parallel.ForEach
大概是这样的:
private BlockingCollection<Job> jobs = new BlockingCollection<Job>();
private Task jobprocessor;
public void StartWork() {
timer.Start();
jobprocessor = Task.Factory.StartNew(RunJobs);
}
public void EndWork() {
timer.Stop();
jobs.CompleteAdding();
jobprocessor.Wait();
}
public void TimerTick() {
var job = new Job();
if (job.NeedsMoreWork())
jobs.Add(job);
}
public void RunJobs() {
var options = new ParallelOptions { MaxDegreeOfParallelism = 10 };
Parallel.ForEach(jobs.GetConsumingPartitioner(), options,
job => job.DoSomething());
}
private BlockingCollection作业=新建BlockingCollection();
专用任务处理器;
公众的