Skip to main content

Open-WebUI-Functions is here! New Pipelines, Filters, and more. Learn more

Parallel LINQ in WinUI apps

Parallel LINQ (PLINQ) brings parallel execution semantics to familiar LINQ queries, letting you scale CPU-bound workloads across cores with minimal syntax changes.

Learn more

Overview

  • Convert any IEnumerable<T> pipeline into a parallel query with AsParallel().
  • Control parallelism with WithDegreeOfParallelism and fallback to sequential execution using AsSequential() when needed.
  • Always marshal results back to the UI thread (with DispatcherQueue) before touching WinUI controls.

Prerequisites

  • .NET 6+ WinUI app targeting desktop scenarios
  • Workloads that are CPU-bound or involve large in-memory datasets
  • Awareness of thread safety for any shared state accessed inside query delegates

Filter and group packages in parallel

The following example filters installed packages for a user and groups them by publisher while evaluating the query in parallel.

Filter packages
var packages = PackageManager.FindPackagesForUser(sid.Value)
.AsParallel()
.WithDegreeOfParallelism(Environment.ProcessorCount - 1)
.Where(pkg => pkg.Id.Publisher.Contains("Microsoft", StringComparison.OrdinalIgnoreCase))
.GroupBy(pkg => pkg.Id.Name)
.OrderByDescending(group => group.Count())
.ToList();

Avoid mutating captured variables inside PLINQ queries. Use local aggregates or thread-safe collections like ConcurrentBag<T> if you need to accumulate results.

Cancellation and ordering

  • Pass a CancellationToken via WithCancellation(token) so users can stop long-running operations from the UI.
  • Use AsOrdered() when the output needs to preserve the original sequence; otherwise, let PLINQ reorder elements for maximum throughput.
  • Combine WithExecutionMode(ParallelExecutionMode.ForceParallelism) only after profiling—forcing parallel execution can degrade performance when datasets are small.

Performance checklist

  • Measure before and after adding PLINQ; the overhead of partitioning can outweigh benefits for small collections.
  • Prefer pure functions in query operators to keep work deterministic and debuggable.
  • Batch UI updates by projecting results into DTOs, then update controls on the dispatcher thread to avoid cross-thread exceptions.