slogan3

Ontwikkel een C# applicatie met asynchrone taken en multithreading

description

Met deze prompt leer ik hoe ik efficiënte en responsieve C# applicaties kan maken die meerdere taken tegelijk uitvoeren. Het helpt problemen met blocking en threadbeheer oplossen en leert best practices voor asynchrone programmering, wat mijn applicaties robuuster en gebruiksvriendelijker maakt.

prompt

Help me bij het ontwikkelen van een C# applicatie die gebruikmaakt van asynchrone taken en multithreading om efficiënte en responsive funct ...

try_prompt

generate_helper
disclaimerOnPageApi

ai_answers

provider: openai
model: gpt-4.1-nano
Natuurlijk! Hier is een overzicht van hoe je in C# een asynchrone en multi-threaded bestandsdownloader kunt maken die meerdere bestanden gelijktijdig downloadt en de voortgang toont: ### Belangrijkste punten: - Gebruik `async` en `await` voor asynchrone operaties. - Gebruik `HttpClient` voor het downloaden van bestanden. - Maak meerdere downloadtaken aan en start ze gelijktijdig. - Gebruik een `Progress<T>` object om voortgang te rapporteren. - Gebruik `ConcurrentBag` of andere thread-safe collecties indien nodig. --- ### Voorbeeldcode: ```csharp using System; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; using System.IO; class Program { static async Task Main(string[] args) { // URLs van de bestanden die je wilt downloaden var urls = new List<string> { "https://example.com/file1.zip", "https://example.com/file2.zip", "https://example.com/file3.zip" }; // Een lijst van taken voor de downloads var downloadTasks = new List<Task>(); // Progress rapportage per bestand var progressHandlers = new List<IProgress<double>>(); for (int i = 0; i < urls.Count; i++) { int index = i; // lokale variabele voor closure var progress = new Progress<double>(p => { Console.WriteLine($"Bestand {index + 1} voortgang: {p:P2}"); }); progressHandlers.Add(progress); } // Start alle downloads gelijktijdig for (int i = 0; i < urls.Count; i++) { downloadTasks.Add(DownloadFileAsync(urls[i], $"bestand_{i + 1}.bin", progressHandlers[i])); } await Task.WhenAll(downloadTasks); Console.WriteLine("Alle bestanden zijn gedownload."); } static async Task DownloadFileAsync(string url, string destinationPath, IProgress<double> progress) { using (HttpClient client = new HttpClient()) { // Vraag de inhoud op zonder direct te downloaden using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead)) { response.EnsureSuccessStatusCode(); var totalBytes = response.Content.Headers.ContentLength ?? -1L; var canReportProgress = totalBytes != -1; using (var stream = await response.Content.ReadAsStreamAsync()) using (var fileStream = new FileStream(destinationPath, FileMode.Create, FileAccess.Write, FileShare.None)) { var buffer = new byte[81920]; long totalRead = 0; int bytesRead; while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0) { await fileStream.WriteAsync(buffer, 0, bytesRead); totalRead += bytesRead; if (canReportProgress) { double progressPercentage = (double)totalRead / totalBytes; progress.Report(progressPercentage); } } } } } } } ``` --- ### Uitleg: - **Main method**: - Maakt een lijst met URLs. - Maakt voor elk bestand een `Progress<double>` object dat de voortgang toont. - Start alle downloads gelijktijdig met `DownloadFileAsync`. - Wacht tot alle taken voltooid zijn met `Task.WhenAll`. - **DownloadFileAsync**: - Gebruikt `HttpClient` om het bestand te downloaden. - Leest het response stream stukje bij beetje. - Schrijft de data naar een bestand. - Rapporteert de voortgang door de `IProgress<double>` interface te gebruiken. ### Tips: - Gebruik `HttpClient` één keer per applicatie (bijvoorbeeld als statisch veld) voor betere prestaties. - Voeg foutafhandeling toe voor robuuste applicaties. - Pas de buffer grootte aan afhankelijk van je behoeften. --- Heeft u verdere vragen of specifieke wensen voor de functionaliteit?
provider: deepseek
model: deepseek-chat
Ik help je graag met het ontwikkelen van een efficiënte bestandsdownloader in C#. Hier is een complete implementatie met uitleg: ## BestandsDownloader Klasse ```csharp using System; using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Threading; using System.Threading.Tasks; public class BestandsDownloader { private readonly HttpClient _httpClient; private readonly SemaphoreSlim _semaphore; private int _voltooideDownloads = 0; private int _totaalDownloads = 0; public event EventHandler<DownloadVoortgangEventArgs>? DownloadVoortgang; public BestandsDownloader(int maxGelijktijdigeDownloads = 5) { _httpClient = new HttpClient(); _semaphore = new SemaphoreSlim(maxGelijktijdigeDownloads, maxGelijktijdigeDownloads); } public async Task DownloadBestandenAsync(List<DownloadTaak> downloadTaken) { _totaalDownloads = downloadTaken.Count; _voltooideDownloads = 0; var downloadTasks = new List<Task>(); foreach (var taak in downloadTaken) { // Wacht op beschikbare slot in semaphore await _semaphore.WaitAsync(); downloadTasks.Add(Task.Run(async () => { try { await DownloadBestandAsync(taak); } finally { _semaphore.Release(); Interlocked.Increment(ref _voltooideDownloads); OnDownloadVoortgang(new DownloadVoortgangEventArgs( _voltooideDownloads, _totaalDownloads, taak.Bestandsnaam)); } })); } // Wacht op voltooiing van alle downloads await Task.WhenAll(downloadTasks); } private async Task DownloadBestandAsync(DownloadTaak taak) { using var response = await _httpClient.GetAsync(taak.Url, HttpCompletionOption.ResponseHeadersRead); response.EnsureSuccessStatusCode(); using var contentStream = await response.Content.ReadAsStreamAsync(); using var fileStream = new FileStream(taak.BestemmingPad, FileMode.Create, FileAccess.Write); await contentStream.CopyToAsync(fileStream); } protected virtual void OnDownloadVoortgang(DownloadVoortgangEventArgs e) { DownloadVoortgang?.Invoke(this, e); } } public class DownloadTaak { public string Url { get; set; } = string.Empty; public string BestemmingPad { get; set; } = string.Empty; public string Bestandsnaam => Path.GetFileName(BestemmingPad); } public class DownloadVoortgangEventArgs : EventArgs { public int VoltooideDownloads { get; } public int TotaalDownloads { get; } public string Bestandsnaam { get; } public double VoortgangPercentage => (double)VoltooideDownloads / TotaalDownloads * 100; public DownloadVoortgangEventArgs(int voltooide, int totaal, string bestandsnaam) { VoltooideDownloads = voltooide; TotaalDownloads = totaal; Bestandsnaam = bestandsnaam; } } ``` ## Gebruiksvoorbeeld ```csharp class Program { static async Task Main(string[] args) { var downloader = new BestandsDownloader(maxGelijktijdigeDownloads: 3); // Abonneer op voortgangsgebeurtenis downloader.DownloadVoortgang += (sender, e) => { Console.WriteLine($"Voortgang: {e.VoltooideDownloads}/{e.TotaalDownloads} " + $"({e.VoortgangPercentage:F1}%) - Laatste: {e.Bestandsnaam}"); }; var downloadTaken = new List<DownloadTaak> { new DownloadTaak { Url = "https://example.com/bestand1.zip", BestemmingPad = @"C:\Downloads\bestand1.zip" }, new DownloadTaak { Url = "https://example.com/bestand2.pdf", BestemmingPad = @"C:\Downloads\bestand2.pdf" }, new DownloadTaak { Url = "https://example.com/bestand3.jpg", BestemmingPad = @"C:\Downloads\bestand3.jpg" } // Voeg meer bestanden toe... }; try { Console.WriteLine("Start downloaden van bestanden..."); await downloader.DownloadBestandenAsync(downloadTaken); Console.WriteLine("Alle downloads voltooid!"); } catch (Exception ex) { Console.WriteLine($"Fout tijdens downloaden: {ex.Message}"); } } } ``` ## Belangrijke Technieken Uitleg: ### 1. **Async/Await Pattern** - `async`/`await` zorgt voor niet-blokkerende operaties - Behoudt responsive UI in desktop apps - Efficient gebruik van thread pool ### 2. **SemaphoreSlim** - Beperkt gelijktijdige downloads naar ingesteld maximum - Voorkomt overbelasting van netwerk/server - `WaitAsync()` is niet-blokkerend ### 3. **Thread Safety** - `Interlocked.Increment()` voor atomic operations - Thread-safe voortgangsrapportage - Geen race conditions ### 4. **HttpClient Best Practices** - Hergebruik van HttpClient instantie - `HttpCompletionOption.ResponseHeadersRead` voor streaming - Efficient geheugengebruik bij grote bestanden ### 5. **Event-based Progress Reporting** - Real-time voortgangsupdates - Losse koppeling tussen downloader en UI - Makkelijk uit te breiden ## Aanvullende Verbeteringen: ```csharp // Voor betere foutafhandeling: public async Task<bool> DownloadBestandenAsync(List<DownloadTaak> downloadTaken, CancellationToken cancellationToken = default) { // Implementatie met cancellation support } // Voor gedetailleerde voortgang per bestand: public class BestandsVoortgang { public long TotaleGrootte { get; set; } public long Gedownload { get; set; } public double Percentage => (double)Gedownload / TotaleGrootte * 100; } ``` Deze implementatie biedt een schaalbare, efficiënte oplossing voor gelijktijdige bestandsdownloads met real-time voortgangsrapportage!