Creëer een geavanceerde C#-functie voor asynchrone data verwerking
description
Met deze prompt kan de gebruiker een op maat gemaakte C#-functie ontwikkelen die efficiënt en veilig asynchroon data verwerkt. Het helpt bij het vermijden van veelvoorkomende valkuilen in async-programmering en verbetert de performance en stabiliteit van applicaties. Dit is waardevoller dan generieke codevoorbeelden omdat het zich richt op praktische integratie en best practices.
prompt
Ontwerp een C#-functie die asynchroon data verwerkt volgens de volgende specificaties: <beschrijf de functionaliteit of het data type>. Geef ook voorbeelden van ...
try_prompt
generate_helper
disclaimerOnPageApi
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Hier is een voorbeeld van een C#-functie die asynchroon een groot tekstbestand leest en parseert. Daarna geef ik een voorbeeld van integratie met async/await en enkele best practices voor foutafhandeling en prestatieoptimalisatie.
### Voorbeeldfunctie: Asynchroon lezen en parsen van een groot tekstbestand
```csharp
using System;
using System.IO;
using System.Threading.Tasks;
public class DataProcessor
{
public async Task ProcessLargeFileAsync(string filePath, Func<string, Task> parseLineAsync)
{
try
{
// Open het bestand asynchroon met een StreamReader
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 81920, useAsync: true))
using (var reader = new StreamReader(stream))
{
string line;
while ((line = await reader.ReadLineAsync()) != null)
{
try
{
// Roep de parseerfunctie asynchroon aan
await parseLineAsync(line);
}
catch (Exception parseEx)
{
// Foutafhandeling per regel, bijvoorbeeld logging
Console.WriteLine($"Fout bij parseren regel: {parseEx.Message}");
// Afhankelijk van de situatie kun je kiezen de fout te negeren of de verwerking te stoppen
}
}
}
}
catch (Exception ex)
{
// Algemene foutafhandeling
Console.WriteLine($"Fout bij lezen van bestand: {ex.Message}");
throw; // of afhandelen zoals nodig
}
}
}
```
### Voorbeeld van integratie in een bestaand project met async/await
```csharp
public class Program
{
public static async Task Main(string[] args)
{
var processor = new DataProcessor();
// Definitie van de parseerfunctie
async Task ParseLine(string line)
{
// Voorbeeld: eenvoudige verwerking
await Task.Run(() =>
{
// Simuleer verwerking
Console.WriteLine($"Verwerkt regel: {line}");
});
}
string bestandPad = "grootbestand.txt";
await processor.ProcessLargeFileAsync(bestandPad, ParseLine);
Console.WriteLine("Verwerking voltooid");
}
}
```
### Best practices voor foutafhandeling en performance optimalisatie
1. **Gebruik van `using` en `useAsync: true`**: Zorg dat het bestand asynchroon wordt geopend en gelezen, wat betere prestaties oplevert bij grote bestanden.
2. **Per regel foutafhandeling**: Fouten tijdens het parseren worden per regel afgehandeld, zodat een fout in één regel niet de hele verwerking stopt.
3. **Buffergrootte instellen**: Het instellen van een buffer (bijvoorbeeld 81920 bytes) kan de I/O-prestaties verbeteren.
4. **Parallelisatie (optioneel)**: Voor verdere optimalisatie kun je overwegen om verwerking van regels te paralleliseren, bijvoorbeeld met `Parallel.ForEachAsync` (vanaf .NET 6) of andere methoden, afhankelijk van de complexiteit en resourcegebruik.
5. **Logging en monitoring**: Voeg logging toe voor fouten en prestaties, zodat je de verwerking kunt monitoren en optimaliseren.
6. **Exception handling**: Zorg dat je uitzonderingen niet onnodig doorgeeft, maar afhandelt waar nodig, vooral bij I/O-operaties en parsing.
7. **Resourcebeheer**: Gebruik `using`-blokken en sluit bestanden correct af om resource leaks te voorkomen.
---
Heeft u nog specifieke wensen of vragen over de implementatie?
provider: deepseek
model: deepseek-chat
Hier is een complete implementatie met integratievoorbeelden en best practices:
## Kernfunctie: Asynchrone Bestandsverwerking
```csharp
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System.Text;
public class AsyncFileProcessor
{
private const int DefaultBufferSize = 4096;
private const FileOptions DefaultFileOptions = FileOptions.Asynchronous | FileOptions.SequentialScan;
public async Task<List<string>> ProcessLargeFileAsync(string filePath,
Func<string, Task<string>> processingFunction = null,
IProgress<int> progress = null)
{
var results = new List<string>();
long totalBytes = 0;
long processedBytes = 0;
try
{
// Controleer bestandsexistentie asynchroon
if (!File.Exists(filePath))
throw new FileNotFoundException($"Bestand niet gevonden: {filePath}");
totalBytes = new FileInfo(filePath).Length;
using (var stream = new FileStream(filePath, FileMode.Open,
FileAccess.Read, FileShare.Read, DefaultBufferSize, DefaultFileOptions))
using (var reader = new StreamReader(stream, Encoding.UTF8))
{
string line;
while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) != null)
{
if (!string.IsNullOrWhiteSpace(line))
{
string processedLine = processingFunction != null
? await processingFunction(line).ConfigureAwait(false)
: line;
results.Add(processedLine);
}
processedBytes += Encoding.UTF8.GetByteCount(line) + 2; // +2 voor CRLF
progress?.Report((int)((processedBytes * 100) / totalBytes));
}
}
return results;
}
catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException)
{
// Log specifieke bestandsgerelateerde fouten
throw new InvalidOperationException($"Fout tijdens bestandsverwerking: {ex.Message}", ex);
}
}
}
```
## Integratievoorbeelden
### Basisintegratie:
```csharp
public class MyDataService
{
private readonly AsyncFileProcessor _fileProcessor = new AsyncFileProcessor();
public async Task ProcessDataFileAsync(string filePath)
{
try
{
var progress = new Progress<int>(percent =>
{
Console.WriteLine($"Verwerkt: {percent}%");
});
var results = await _fileProcessor.ProcessLargeFileAsync(
filePath,
ProcessLineAsync,
progress);
Console.WriteLine($"Verwerking voltooid. {results.Count} regels verwerkt.");
}
catch (Exception ex)
{
await LogErrorAsync($"Verwerking mislukt: {ex.Message}");
throw;
}
}
private async Task<string> ProcessLineAsync(string line)
{
// Simuleer asynchrone verwerking
await Task.Delay(1); // Vervang door echte async operatie
return line.ToUpperInvariant();
}
private Task LogErrorAsync(string message)
{
// Asynchrone logging implementatie
return Task.CompletedTask;
}
}
```
### Gebruik in ASP.NET Core Controller:
```csharp
[ApiController]
[Route("api/files")]
public class FileProcessingController : ControllerBase
{
[HttpPost("process")]
public async Task<IActionResult> ProcessFile([FromForm] IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest("Geen bestand geüpload");
var tempFilePath = Path.GetTempFileName();
try
{
using (var stream = new FileStream(tempFilePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
var processor = new AsyncFileProcessor();
var results = await processor.ProcessLargeFileAsync(tempFilePath);
return Ok(new { ProcessedLines = results.Count });
}
finally
{
if (System.IO.File.Exists(tempFilePath))
System.IO.File.Delete(tempFilePath);
}
}
}
```
## Best Practices
### Foutafhandeling:
```csharp
public async Task SafeFileProcessingAsync(string filePath)
{
try
{
var results = await _fileProcessor.ProcessLargeFileAsync(filePath);
// Verwerk resultaten
}
catch (FileNotFoundException ex)
{
await LogErrorAsync($"Bestand niet gevonden: {ex.FileName}");
}
catch (IOException ex)
{
await LogErrorAsync($"I/O fout: {ex.Message}");
}
catch (UnauthorizedAccessException)
{
await LogErrorAsync("Geen toegangsrechten voor bestand");
}
catch (Exception ex)
{
await LogErrorAsync($"Onverwachte fout: {ex.Message}");
throw; // Re-throw voor hoger niveau
}
}
```
### Performance Optimalisatie:
1. **Buffer Grootte**:
```csharp
private const int OptimalBufferSize = 8192; // 8KB voor moderne systemen
```
2. **Batched Verwerking**:
```csharp
public async Task ProcessInBatchesAsync(string filePath, int batchSize = 1000)
{
var batch = new List<string>(batchSize);
await foreach (var line in ReadLinesAsync(filePath))
{
batch.Add(line);
if (batch.Count >= batchSize)
{
await ProcessBatchAsync(batch);
batch.Clear();
}
}
if (batch.Count > 0)
await ProcessBatchAsync(batch);
}
private async IAsyncEnumerable<string> ReadLinesAsync(string filePath)
{
using var stream = new FileStream(filePath, FileMode.Open,
FileAccess.Read, FileShare.Read, DefaultBufferSize, DefaultFileOptions);
using var reader = new StreamReader(stream);
string line;
while ((line = await reader.ReadLineAsync()) != null)
{
yield return line;
}
}
```
3. **Parallelle Verwerking**:
```csharp
public async Task<List<string>> ProcessParallelAsync(string filePath)
{
var lines = await File.ReadAllLinesAsync(filePath);
var tasks = lines.Select(async line =>
{
await Task.Delay(1); // Simuleer async werk
return line.ToUpper();
});
return (await Task.WhenAll(tasks)).ToList();
}
```
### Belangrijkste Tips:
- Gebruik altijd `ConfigureAwait(false)` in library code
- Implementeer progress reporting voor lange operaties
- Gebruik `IAsyncDisposable` voor resource cleanup
- Limiteer parallelisme bij I/O-bound operations
- Gebruik geheugen-efficiente data structuren voor grote bestanden
Deze implementatie volgt async/await best practices en biedt flexibele integratiemogelijkheden voor verschillende scenario's.