67 lines
1.9 KiB
C#
67 lines
1.9 KiB
C#
using DownloadManager.Core.Models;
|
||
using System.Collections.Generic;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace DownloadManager.Core.Queue;
|
||
|
||
public class DownloadQueue
|
||
{
|
||
private SemaphoreSlim _concurrencySemaphore;
|
||
private readonly SemaphoreSlim _itemsAvailableSemaphore = new(0);
|
||
private readonly PriorityQueue<DownloadItem, int> _inner = new();
|
||
private readonly object _lock = new();
|
||
|
||
public DownloadQueue(int maxConcurrent = 3)
|
||
=> _concurrencySemaphore = new SemaphoreSlim(maxConcurrent, maxConcurrent);
|
||
|
||
public void Enqueue(DownloadItem item)
|
||
{
|
||
lock (_lock)
|
||
{
|
||
_inner.Enqueue(item, item.Priority);
|
||
_itemsAvailableSemaphore.Release();
|
||
}
|
||
}
|
||
|
||
public async Task<DownloadItem?> DequeueAsync(CancellationToken ct)
|
||
{
|
||
// Önce bir slotun boşalmasını bekle (concurrency limit)
|
||
await _concurrencySemaphore.WaitAsync(ct);
|
||
|
||
try
|
||
{
|
||
// Sonra kuyrukta bir öğe olmasını bekle
|
||
await _itemsAvailableSemaphore.WaitAsync(ct);
|
||
|
||
lock (_lock)
|
||
{
|
||
if (_inner.TryDequeue(out var item, out _))
|
||
return item;
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
_concurrencySemaphore.Release();
|
||
throw;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
public void Release() => _concurrencySemaphore.Release();
|
||
|
||
/// <summary>Çalışma zamanında limit değiştir (ayarlar panelinden)</summary>
|
||
public void SetConcurrencyLimit(int newLimit)
|
||
{
|
||
lock (_lock)
|
||
{
|
||
// Not: Bu basit uygulama çalışma anındaki limit değişimini tam olarak yansıtmayabilir,
|
||
// ama temel yapı için yeterli.
|
||
var old = _concurrencySemaphore;
|
||
_concurrencySemaphore = new SemaphoreSlim(newLimit, newLimit);
|
||
old.Dispose();
|
||
}
|
||
}
|
||
}
|