Skip to content

Multithreaded parallel downloads with auto-scroll and queue UI controls - #1885

Open
SirBiggin wants to merge 5 commits into
rmcrackan:masterfrom
SirBiggin:master
Open

Multithreaded parallel downloads with auto-scroll and queue UI controls#1885
SirBiggin wants to merge 5 commits into
rmcrackan:masterfrom
SirBiggin:master

Conversation

@SirBiggin

Copy link
Copy Markdown

Summary

  • Parallel downloads: Download and DeDRM multiple audiobooks simultaneously using a configurable thread pool (defaults to processor count). Uses a HashSet<Task> loop allowing dynamic concurrency changes mid-run.
  • Auto-scroll: The download queue automatically scrolls to keep active downloads in view via a new ScrollToTop method on VirtualFlowControl.
  • UI controls: Added two checkboxes to the Process Queue panel — Auto-scroll and Parallel downloads — alongside the existing Cancel All and DL Limit controls.
  • Thread-safety fix: Fixed InvalidOperationException crash in setLiberatedVisibleMenuItem caused by enumerating GetVisible() on a background thread while parallel downloads modified the collection. Collection is now snapshotted on the UI thread before being passed to Task.Run.
  • TrackedQueue multi-active: Replaced single Current item with an _active list to track multiple simultaneous downloads, while keeping the backward-compatible Current property.
  • Settings: Added AutoScrollQueue (bool) and MaxConcurrentDownloads (int) persistent settings.

Test plan

  • Start multiple downloads and confirm they run in parallel
  • Toggle Parallel downloads checkbox off mid-run and confirm it serializes
  • Toggle Auto-scroll and confirm queue scrolls/stops scrolling to active items
  • Confirm no InvalidOperationException crash during parallel downloads
  • Confirm Cancel All cancels all active downloads
  • Confirm settings persist across restarts

SirBiggin and others added 5 commits June 16, 2026 10:23
# Conflicts:
#	Source/LibationUiBase/ProcessQueue/ProcessQueueViewModel.cs
…l downloads

Snapshot GetVisible() on the UI thread before handing off to Task.Run,
preventing InvalidOperationException when parallel downloads modify the
collection concurrently. Also fix installer script to use 64-bit dotnet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@rmcrackan rmcrackan left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry it has taken me so long to get back to this.

Thanks for this - the concurrent queue loop and multi-active TrackedQueue are a solid foundation. A few gaps before this is safe to merge:

  1. Avalonia parity - Parallelism is on by default in shared UI code, but Avalonia has no toggle and Cancel All still only cancels Current (see ProcessQueueControl.axaml.cs).
  2. Abort / disk-full - Please also cancel in-flight active downloads, not just clear the pending queue.
  3. Safer defaults - Defaulting to ProcessorCount is aggressive given Audible license throttling; prefer opt-in or a small default, plus a way to set the limit.
  4. Installer script - Please drop the hardcoded dotnet.exe path; it looks unrelated to this feature.

Also worth rebasing on current master when you get a chance.

SpeedLimit = Configuration.Instance.DownloadSpeedLimit / 1024m / 1024;
MaxConcurrentDownloads = Configuration.Instance.MaxConcurrentDownloads;
AutoScrollQueue = Configuration.Instance.AutoScrollQueue;
MultiThreadEnabled = true;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this lives in shared UI code, Avalonia gets parallel downloads with no control to turn them off. Could we default to off (or persist the setting) and add matching Avalonia UI?


if (result == ProcessBookResult.FailedAbort)
{
abortCts.Cancel();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClearQueue() stops new work, but other active downloads keep running. Could we cancel all Active items here (same as Cancel All)? Same for the disk-full path just below.

{
var value = GetNonString(defaultValue: 0);
// Treat 0 or 1 as "use default" — 1 may have been written by an earlier bug.
return value <= 1 ? Environment.ProcessorCount : value;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defaulting to ProcessorCount may trigger Audible license denials on larger machines. A small default (e.g. 2-3) and a numeric control would be safer than an on/off checkbox alone.

dotnet publish 'LoadByOS/WindowsConfigApp/WindowsConfigApp.csproj' @publishArgs
dotnet publish 'LibationCli/LibationCli.csproj' @publishArgs
dotnet publish "Hangover$Ui/Hangover$Ui.csproj" @publishArgs
& "C:\Program Files\dotnet\dotnet.exe" publish "Libation$Ui/Libation$Ui.csproj" @publishArgs

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mind leaving this out of the PR? Hardcoding C:\Program Files\dotnet\dotnet.exe is machine-specific and unrelated to parallel downloads.

@SirBiggin

SirBiggin commented Jul 25, 2026 via email

Copy link
Copy Markdown
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants