我有一个集成服务,它运行计算繁重的数据绑定过程。我想确保在这些进程中运行的n = 5,n = 5(但是n将是可配置的,在运行时可更改的)。我们的想法是将服务器上的负载限制在安全水平。该方法处理的数据量受批量限制,因此我不需要担心1个进程代表比另一个更大的负载。
处理方法由另一个进程调用,其中运行工资单的请求保存在队列中,我可以在该点插入一些逻辑以确定是立即处理此请求,还是将其留在队列中。
所以我想在与处理方法相同的服务上使用一个单独的方法,它可以告诉我服务器是否可以接受对处理方法的另一个调用。它会问,“有多少工资单正在运行?是不是n?”什么是实现这一目标的巧妙方法?
----------- ------------编辑
我认为我需要说清楚,决定是否将请求从队列中取出的过程与从WCF边界处理工资核算数据的服务分开。停止工资单处理过程中的一个线程不会阻止更多的请求进入
答案 0 :(得分:4)
您可以使用Semaphore
执行此操作。
public class Foo
{
private Semaphore semaphore;
public Foo(int numConcurrentCalls)
{
semaphore = new Semaphore(numConcurrentCalls, numConcurrentCalls);
}
public bool isReady()
{
return semaphore.WaitOne(0);
}
public void Bar()
{
try
{
semaphore.WaitOne();//it will only get past this line if there are less than
//"numConcurrentCalls" threads in this method currently.
//do stuff
}
finally
{
semaphore.Release();
}
}
}
答案 1 :(得分:1)
查看Object Pool模式。这就是你所描述的。虽然模式不是严格要求,但您可以公开池中当前对象的数量,最大(已配置)数字,高水位等。
答案 2 :(得分:0)
我认为你可能想要一个BlockingCollection,其中集合中的每个项目代表一个并发调用。
另见IProducerConsumerCollection。
如果您只是使用线程,我建议您查看限制线程并发的方法(例如TaskScheduler.MaximumConcurrencyLevel属性和this example。)。
答案 3 :(得分:0)
void ThreadTest()
{
ConcurrentQueue<int> q = new ConcurrentQueue<int>();
int MaxCount = 5;
Random r = new Random();
for (int i = 0; i <= 10000; i++)
{
q.Enqueue(r.Next(100000, 200000));
}
ThreadStart proc = null;
proc = () =>
{
int read = 0;
if (q.TryDequeue(out read))
{
Console.WriteLine(String.Format("[{1:HH:mm:ss}.{1:fff}] starting: {0}... @Thread {2}", read, DateTime.Now, Thread.CurrentThread.ManagedThreadId));
Thread.Sleep(r.Next(100, 1000));
Console.WriteLine(String.Format("[{1:HH:mm:ss}.{1:fff}] {0} ended! @Thread {2}", read, DateTime.Now, Thread.CurrentThread.ManagedThreadId));
proc();
}
};
for (int i = 0; i <= MaxCount; i++)
{
new Thread(proc).Start();
}
}