/// <summary> /// Increases the total size of the pool by the amount specified. /// </summary> /// <param name="increaseBy">The amount of values to increase the pool by.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns></returns> public async Task IncreasePoolSizeAsync(int increaseBy = 1, CancellationToken cancellationToken = default(CancellationToken)) { if (IsDisposed || IsDisposing) { throw new ObjectDisposedException(this.GetType().Name); } if (increaseBy < 0) { throw new ArgumentOutOfRangeException(nameof(increaseBy)); } for (int i = 0; i < increaseBy; i++) { cancellationToken.ThrowIfCancellationRequested(); var instance = await Task.Run(() => InstanceBuilder.Invoke(cancellationToken), cancellationToken).ConfigureAwait(false); await Task.Run(() => { PooledInstances.Enqueue(instance); }, cancellationToken).ConfigureAwait(false); Interlocked.Increment(ref _totalInstancesCount); RaisePropertyChanged(nameof(TotalInstancesCount)); } }
/// <summary> /// Acquires the next available pooled value. /// </summary> /// <param name="pooledValueAcquisitionMode">The pooled value acquisition mode.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns></returns> public async Task <Pooled <TValue> > AcquirePooledValueAsync( PooledValueAcquisitionMode pooledValueAcquisitionMode = PooledValueAcquisitionMode.AvailableInstanceOrDefaultValue, CancellationToken cancellationToken = default(CancellationToken)) { if (IsDisposed || IsDisposing) { throw new ObjectDisposedException(this.GetType().Name); } TValue value = default(TValue); // check whether we actually currently have any instances left if (PooledInstances.IsEmpty) { if (pooledValueAcquisitionMode == PooledValueAcquisitionMode.AvailableInstanceOrDefaultValue) { return(default(Pooled <TValue>)); } else if (pooledValueAcquisitionMode == PooledValueAcquisitionMode.AvailableInstanceOrCreateNewOne) { try { value = await Task.Run(() => InstanceBuilder.Invoke(cancellationToken), cancellationToken).ConfigureAwait(false); } catch (TargetInvocationException targetInvocationException) { targetInvocationException.InnerException.ThrowIfNotNull(); } } else { while (PooledInstances.IsEmpty || PooledInstances.TryDequeue(out value) == false) { cancellationToken.ThrowIfCancellationRequested(); await Task.Yield(); } } } else { // try to retrieve the next available / queued value if (PooledInstances.TryDequeue(out value) == false) { if (pooledValueAcquisitionMode == PooledValueAcquisitionMode.AvailableInstanceOrDefaultValue) { return(default(Pooled <TValue>)); } else if (pooledValueAcquisitionMode == PooledValueAcquisitionMode.AvailableInstanceOrCreateNewOne) // build a new one { try { value = await Task.Run(() => InstanceBuilder.Invoke(cancellationToken), cancellationToken).ConfigureAwait(false); } catch (TargetInvocationException targetInvocationException) { targetInvocationException.InnerException.ThrowIfNotNull(); } } else { // keep trying while (PooledInstances.TryDequeue(out value) == false) { cancellationToken.ThrowIfCancellationRequested(); await Task.Yield(); } } } } RaisePropertyChanged(nameof(AvailableInstancesCount)); cancellationToken.ThrowIfCancellationRequested(); return(new Pooled <TValue>(value, this)); }