任务计数器C#,联锁
我希望并行运行任务,在给定时间运行的实例不超过10个 这是我目前掌握的代码:任务计数器C#,联锁,c#,task,C#,Task,我希望并行运行任务,在给定时间运行的实例不超过10个 这是我目前掌握的代码: private void Listen() { while (true) { var context = listener.GetContext(); var task = Task.Run(() => HandleContextAsync(context)); Interlocked.Increment(ref countTask);
private void Listen()
{
while (true)
{
var context = listener.GetContext();
var task = Task.Run(() => HandleContextAsync(context));
Interlocked.Increment(ref countTask);
if (countTask > 10)
{
//I save tasks in the collection
}
else
{
task.ContinueWith(delegate { Interlocked.Decrement(ref countTask); }); //I accomplish the task and reduce the counter
}
}
}
我建议您使用并行循环;例如:
Parallel.For(1, 10, a =>
{
var context = listener.GetContext();
...
});
这将启动定义数量的任务,而无需您自己管理流程。如果您希望连续并行执行代码,一次最多10个实例,这可能值得考虑:
private void Listen()
{
var options = new ParallelOptions() { MaxDegreeOfParallelism = 10 };
Parallel.For(1, long.MaxValue - 1, options, (i) =>
{
var context = listener.GetContext();
HandleContextAsync(context);
});
}
基本上,它将连续运行代码(大致是
long.MaxValue
次)MaxDegreeOfParallelism
确保它一次只运行10个代码“实例”。我假设GetContext
的结果不是由您创建的,因此,如果您不知道要运行多少次或者没有立即处理所有上下文,那么使用并行可能没有用
因此,解决这个问题的最佳方法可能是实现您自己的TaskScheduler
。通过这种方式,您可以添加更多的任务,以便在具有固定并发级别的情况下按需解决
根据网站上的例子,你已经可以做到这一点
我制作了一个示例程序,对网站上的limitedconcurrentyleveltaskscheduler
进行了一些更改
使用系统;
使用System.Collections.Generic;
使用系统线程;
使用System.Threading.Tasks;
名称空间并行
{
班级计划
{
私有静态随机兰德=新随机();
静态void Main(字符串[]参数)
{
var ts=新的LimitedConcurrencyLevel任务调度器(10);
var taskFactory=新taskFactory(ts);
while(true)
{
var-context=GetContext(ts);
if(context.Equals(“Q”,StringComparison.OrdinalIgnoreCase))
打破
StartNew(()=>HandleContextAsync(上下文));
}
控制台。WriteLine(“等待…”);
同时(ts.CountRunning!=0)
{
WriteLine(“正在运行{0}x任务,其中{1}x已排队。”,ts.CountRunning,ts.CountQueued);
螺纹屈服强度();
睡眠(100);
}
}
私有静态void HandleContextAsync(字符串上下文)
{
//延迟1-10秒,使示例更易于理解
Thread.Sleep(Rand.Next(100010000));
WriteLine(“上下文:{0},来自线程:{1}”,上下文,线程.CurrentThread.ManagedThreadId);
}
私有静态字符串GetContext(LimitedConcurrencyLevel任务调度器ts)
{
WriteLine(“正在运行{0}x任务,其中{1}x已排队。”,ts.CountRunning,ts.CountQueued);
返回控制台ReadLine();
}
}
//提供一个任务计划程序,确保在运行时达到最大并发级别
//在线程池的顶部运行。
公共类LimitedConcurrentYlevelTaskScheduler:TaskScheduler
{
//指示当前线程是否正在处理工作项。
[线程静态]
私有静态bool\u currentThreadIsProcessingItems;
//要执行的任务列表
私有只读LinkedList _tasks=new LinkedList();//受锁保护(_tasks)
public int CountRunning=>\u nowlunning;
公共整数排队
{
得到
{
锁定(_任务)
{
return_tasks.Count;
}
}
}
//此计划程序允许的最大并发级别。
私有只读int_maxDegreeOfParallelism;
//指示计划程序当前是否正在处理工作项。
私有volatile int_delegatesquedorrunning=0;
私有volatile int正在运行;
//创建具有指定并行度的新实例。
public limitedconcurrencedyleveltaskscheduler(int-maxDegreeOfParallelism)
{
if(最大平行度<1)
抛出新ArgumentOutOfRangeException(“maxDegreeOfParallelism”);
_maxDegreeOfParallelism=maxDegreeOfParallelism;
}
//将任务排入调度程序队列。
受保护的密封覆盖无效队列任务(任务任务)
{
//将任务添加到要处理的任务列表中。如果没有足够的任务
//当前排队或正在运行以处理任务的代理计划另一个任务。
锁定(_任务)
{
_tasks.AddLast(任务);
如果(_delegatesquedorrunning<_maxDegreeOfParallelism)
{
联锁。增量(参考delegatesquedorunning);
NotifyThreadPoolOfPendingWork();
}
}
}
//通知线程池此计划程序有要执行的工作。
私有void NotifyThreadPoolOfPendingWork()
{
ThreadPool.UnsafeQueueUserWorkItem(=>
{
//请注意,当前线程现在正在处理工作项。
//这是将任务内联到此线程中所必需的。
_currentThreadIsProcessingItems=true;
尝试
{
//处理队列中的所有可用项。
while(true)
{
任务项;
锁定(_任务)
{
//当没有更多要处理的项目时,
//请注意,我们已完成处理,请退出。
如果(_tasks.Count==0)
{
联锁减量(参考DelegateSqueuedoRunning);
打破
}
//得到