【发布时间】:2015-10-03 08:07:36
【问题描述】:
从这个问题继续:
Correct way to implement a resource pool
我现在正在考虑实现允许池的用户继续持有池中的对象的最长时间,但我不确定实现这种事情的正确方法.所以,假设我们有这样的事情:
IFoo GetFooFromPool()
{
if (_sem.Wait(WaitTimeOut))
{
return Pop();
}
throw new WaitTimeoutException("Timed out waiting for Foo instance");
}
所以_sem 是一个信号量,Pop 将从堆栈中弹出一个实例(如果需要,初始化它),到目前为止一切都很好。
当调用者完成IFoo 后,将其返回到堆栈,如下所示:
void ReleaseFoo(IFoo p)
{
if (p == null)
{
throw new ArgumentNullException("Foo parameter is null");
}
Push(p);
_sem.Release();
}
实际上,我用一个使用IDisposable 的包装类来包装所有这些,以确保Foo 被返回到池中。所以从客户端来看,它看起来像这样:
using (var f = myPool.GetDisposableFoo())
{
// Do stuff...
}
我想做的是,如果// Do Stuff 花费的时间太长(或可能挂起),IFoo 将被回收并且调用代码将引发异常。
所以我想到了做这样的事情:
private IFoo Pop()
{
IFoo p;
_stack.TryPop(out p);
if (p == null)
{
p = RunFactory(); // this is lazy initialization of the stack
}
if (MaximumLoanTime > 0)
{
p.CurrentToken = new CancellationTokenSource();
Task.Delay(MaximumLoanTime, p.CurrentToken.Token).ContinueWith(() =>
{
// Timeout, return to the stack
// Inform current owner???
Push(p);
});
}
return p;
}
问题是如何确保当前持有者收到信号,以便它不会继续尝试使用可能正在被其他人使用的IFoo 实例。
【问题讨论】:
标签: c# multithreading pool