我一直在尝试使用Semaphore来控制我的服务可以处理的请求数。即。
class Service : IDisposable {
SemaphoreSlim s = new SemaphoreSlim(InitialCapacity);
....
async void ProcessRequest() {
await s.WaitAsync();
try {
......
} finally {
s.Release();
}
}
}
我遇到的问题有2个我不知道如何解决。我一直在使用类似的黑客来解决这些问题,但我想知道是否有更好的方法
我希望能够动态更改服务类的容量,所以我有类似的东西。
void ChangeCapacity(int newCapacity) {
int extraRequestsCount = newCapacity - oldCapacity;
if (extraRequestsCount > 0) {
s.Release(extraRequestsCount);
}
else if (extraRequestsCount < 0) {
for (int i = 0; i < -extraRequestsCount; i++) {
s.WaitAsync(); // try to steal some resources, over time...
}
}
}
在dispose方法中,我想确保在处理信号量之前完成所有请求处理,否则我的ProcessRequest()中的s.Release()调用会抛出ObjectDisposedException,所以我做了以下
public void Dispose() {
if (s!= null) {
for (int i = 0; i < oldCapacity; i++) {
s.Wait();
}
s.Dispose();
}
}
请注意,我一直在使用循环手动等待多次。如果容量很大,这真的很慢。有一个更好的方法吗?信号量有一个Release(int count),为什么没有Wait(int count)?
答案 0 :(得分:1)
我可能做的是在进行调整时,用一个具有所需容量的新信号量替换你的信号量实例,并将所有未来的工作分配给该信号量。在完成所有线程的引用之前,现有的和现在解除引用的信号量不会被垃圾收集,所以只要你将信号量变量本地分配给每个线程就应该是安全的。