Продолжает от этого вопроса:Реализация бассейна с ограничением по времени
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
, которые могли бы теперь будет использоваться кем-то другим.