mirror of
https://github.com/Crunchy-DL/Crunchy-Downloader.git
synced 2026-05-05 17:59:08 +00:00
- Added **fallback for sync failures** [#407](https://github.com/Crunchy-DL/Crunchy-Downloader/issues/407) - Added **history setting** to remove non-existent series/episodes on refresh [#420](https://github.com/Crunchy-DL/Crunchy-Downloader/issues/420) - Added **movies to history** - Added **queue persistence** - Changed **download item state handling** - Changed **download item removal processing** - Made small changes to **font detection** - Changed **rate limit error handling** - Fixed issue where **files were not always cleaned up** for removed downloads - Fixed **crash when the queue list was modified** - Fixed **changelog parsing** not handling versions like `vX.X.X.X`, which caused changes to be re-added on every restart
79 lines
No EOL
2 KiB
C#
79 lines
No EOL
2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using Avalonia.Threading;
|
|
|
|
namespace CRD.Utils.QueueManagement;
|
|
|
|
public sealed class UiMutationQueue{
|
|
private readonly object syncLock = new();
|
|
private readonly Queue<Action> pendingMutations = new();
|
|
|
|
private readonly Dispatcher dispatcher;
|
|
private readonly DispatcherPriority priority;
|
|
|
|
private bool isProcessing;
|
|
private int pumpScheduled;
|
|
|
|
public UiMutationQueue()
|
|
: this(null, DispatcherPriority.Background){
|
|
}
|
|
|
|
public UiMutationQueue(
|
|
Dispatcher? dispatcher,
|
|
DispatcherPriority priority){
|
|
this.dispatcher = dispatcher ?? Dispatcher.UIThread;
|
|
this.priority = priority;
|
|
}
|
|
|
|
public void Enqueue(Action mutation){
|
|
if (mutation == null)
|
|
throw new ArgumentNullException(nameof(mutation));
|
|
|
|
lock (syncLock){
|
|
pendingMutations.Enqueue(mutation);
|
|
}
|
|
|
|
if (Interlocked.CompareExchange(ref pumpScheduled, 1, 0) != 0)
|
|
return;
|
|
|
|
dispatcher.Post(ProcessPendingMutations, priority);
|
|
}
|
|
|
|
private void ProcessPendingMutations(){
|
|
if (isProcessing)
|
|
return;
|
|
|
|
try{
|
|
isProcessing = true;
|
|
|
|
while (true){
|
|
Action? mutation;
|
|
|
|
lock (syncLock){
|
|
mutation = pendingMutations.Count > 0
|
|
? pendingMutations.Dequeue()
|
|
: null;
|
|
}
|
|
|
|
if (mutation is null)
|
|
break;
|
|
|
|
mutation();
|
|
}
|
|
} finally{
|
|
isProcessing = false;
|
|
Interlocked.Exchange(ref pumpScheduled, 0);
|
|
|
|
bool hasPending;
|
|
lock (syncLock){
|
|
hasPending = pendingMutations.Count > 0;
|
|
}
|
|
|
|
if (hasPending &&
|
|
Interlocked.CompareExchange(ref pumpScheduled, 1, 0) == 0){
|
|
dispatcher.Post(ProcessPendingMutations, priority);
|
|
}
|
|
}
|
|
}
|
|
} |