# Jak używać asynchroniczności i wielowątkowości do operacji z kodami QR w języku C#
Skanowanie kodów QR w trybie jednowątkowym blokuje wątek wywołujący na czas dekodowania każdego obrazu.
W procedurze obsługi przycisku WPF powoduje to zawieszenie interfejsu użytkownika do czasu zakończenia dekodowania. W zadaniu wsadowym przetwarzającym setki obrazów pozostawia rdzenie procesora bezczynne, podczas gdy mogłyby one pracować równolegle. Metoda `ReadAsync` z IronQR przesyła poszczególne odczyty do zadania awaitable, a standardowa metoda `Read` działa z `Parallel.ForEach` i `Task.WhenAll` dla przepustowości wsadowej.
W niniejszym przewodniku pokazano, jak przetwarzać kody QR asynchronicznie, rozdzielać odczyty partii między rdzenie procesora oraz łączyć oba wzorce w przypadku potoków o dużej przepustowości.
*as-heading:2(Szybki start: Asynchroniczne przetwarzanie kodów QR)*
Załaduj obraz i poczekaj na zdekodowane wyniki bez blokowania wątku wywołującego.
```csharp
:title=Quickstart
using IronQr;
using IronSoftware.Drawing;
var input = new QrImageInput(AnyBitmap.FromFile("ticket.png"));
IEnumerable<QrResult> results = await new QrReader().ReadAsync(input);
Console.WriteLine(results.First().Value);
```
<div class="hsg-featured-snippet">
<h3>Minimalny proces (5 kroków)</h3>
<ol>
<li><a class="js-modal-open" data-modal-id="trial-license-after-download" href="https://nuget.org/packages/IronQR/">Pobierz bibliotekę IronQR C# do asynchronicznego przetwarzania kodów QR</a></li>
<li>Użyj <code>ReadAsync</code> do nieblokujących odczytów pojedynczych</li>
<li>Użyj <code>Parallel.ForEach</code> do przetwarzania wsadowego obciążającego procesor</li>
<li>Połącz z <code>SemaphoreSlim,</code> aby uzyskać potoki o ograniczonej współbieżności</li>
<li>Zbierz wyniki z <code>IEnumerable<QRRESULT></code> i wydrukuj zdekodowane wartości</li>
</ol>
</div>
## Asynchroniczne odczytywanie kodów QR
`ReadAsync` zwraca zadanie awaitable, co czyni go kompatybilnym z obsługą zdarzeń WPF/MAUI, akcjami kontrolera ASP.NET lub dowolną metodą asynchroniczną. Dane wejściowe muszą być utworzone z bitmapy obrazu; nie ma przeciążenia ścieżki pliku.
Strona pisania jest synchroniczna i nie ma wariantów asynchronicznych. Aby uniknąć blokowania wątku podczas operacji I/O na plikach, otocz krok zapisywania w `File.WriteAllBytesAsync()` używając surowych bajtów eksportowanych z bitmapy.
### Dane wejściowe
Identyfikator wydarzenia w postaci kodu QR zeskanowany i wygenerowany ponownie w celu zademonstrowania asynchronicznego wzorca odczytu i zapisu.
<div class="content-img-align-center">
<div class="center-image-wrapper" style="max-width: 300px;">
<img src="/static-assets/qr/how-to/async-and-multithreading/input-async-event-badge.webp"
alt="Kodowanie kodu QR https://ironsoftware.com/event-badge używane jako asynchroniczne odczytywanie danych wejściowych"
class="img-responsive add-shadow" />
</div>
</div>
```cs
:path=/static-assets/qr/content-code-examples/how-to/async-and-multithreading/async-read-write.cs
```
### Wynik
Terminal wyświetla dekodowany typ QR i wartość w formacie `[QrType] Value`, a następnie potwierdza, że `output-qr.png` został zapisany.
<div class="content-img-align-center">
<div class="center-image-wrapper">
<img src="/static-assets/qr/how-to/async-and-multithreading/test1-async-out.webp" alt="Wynik na terminalu pokazujący zdekodowaną wartość [QR] oraz potwierdzenie zapisania pliku output-qr.png" class="img-responsive add-shadow" />
</div>
</div>
`QrScanMode.Auto` uruchamia zarówno wykrywanie ML, jak i podstawowe skanowanie, wypełniając zdekodowaną wartość i typ QR w każdym wyniku. `OnlyDetectionModel` jest szybszy, ale zwraca tylko współrzędne pola ograniczającego, pozostawiając pole wartości puste. Użyj `Auto` zawsze, gdy potrzebna jest zakodowana treść.
---
## Przetwarzanie kodów QR z wykorzystaniem wielowątkowości
Dla obrazów, które można dekodować niezależnie, `Parallel.ForEach` rozdziela pracę między dostępne rdzenie CPU. Oddzielna instancja `QrReader` na każdą iterację jest bezpiecznym domyślnym wyborem, ponieważ IronQR nie zapewnia wyraźnej gwarancji bezpieczeństwa wątków dla współdzielonych instancji czytników.
### Dane wejściowe
Cztery z dziesięciu obrazów testowych kodów QR użytych w równoległym skanowaniu partii. Każdy obraz koduje URL i jest odczytywany z folderu `qr-images/` w czasie wykonywania.
<div class="competitors-section__wrapper-even-1">
<div class="competitors__card" style="width: 47%;">
<img src="/static-assets/qr/how-to/async-and-multithreading/input-batch-qr-1.webp"
alt="Wejściowy obraz kodu QR w partii 1 z 10 kodujący https://ironsoftware.com/batch-1"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
Zdjęcie 1 (partia 1 z 10)
</p>
</div>
<div class="competitors__card" style="width: 47%;">
<img src="/static-assets/qr/how-to/async-and-multithreading/input-batch-qr-2.webp"
alt="Wejściowy obraz kodu QR w partii 2 z 10 kodujący https://ironsoftware.com/batch-2"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
Zdjęcie 2 (partia 2 z 10)
</p>
</div>
</div>
<div class="competitors-section__wrapper-even-1">
<div class="competitors__card" style="width: 47%;">
<img src="/static-assets/qr/how-to/async-and-multithreading/input-batch-qr-3.webp"
alt="Wejściowy obraz kodu QR w partii 3 z 10 kodujący https://ironsoftware.com/batch-3"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
Zdjęcie 3 (partia 3 z 10)
</p>
</div>
<div class="competitors__card" style="width: 47%;">
<img src="/static-assets/qr/how-to/async-and-multithreading/input-batch-qr-4.webp"
alt="Wejściowy obraz kodu QR w partii 4 z 10 kodujący https://ironsoftware.com/batch-4"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
Zdjęcie 4 (partia 4 z 10)
</p>
</div>
</div>
```cs
:path=/static-assets/qr/content-code-examples/how-to/async-and-multithreading/parallel-batch.cs
```
### Wynik
Konsola wyświetla podsumowanie partii, w tym liczbę przetworzonych plików, czas przetwarzania, znalezione kody QR, ewentualne błędy oraz przepustowość. Następnie podaje każdą nazwę pliku wraz z jego zdekodowanym adresem URL.
<div class="content-img-align-center">
<div class="center-image-wrapper">
<img src="/static-assets/qr/how-to/async-and-multithreading/test2-async-output.webp" alt="Wynik terminala pokazujący równoległe wyniki partii: 10 przetworzonych plików, znalezione kody QR, błędy, przepustowość i zdekodowany adres URL na nazwę pliku" class="img-responsive add-shadow" />
</div>
</div>
[Pobierz wszystkie 10 obrazów testowych do wprowadzania kodów QR (batch-qr-images.zip).](/static-assets/qr/how-to/async-and-multithreading/batch-qr-images.zip)
`ConcurrentBag<t>` zbiera wyniki ze wszystkich wątków bez potrzeby użycia blokad. Licznik bezpieczny dla wątków śledzi awarie, a użycie try-catch dla każdego pliku gwarantuje, że jeden uszkodzony obraz nie przerwie całej partii. Podejście to jest zgodne z wzorcem izolacji błędów opisanym w poradniku [dotyczącym obsługi błędów](/csharp/qr/how-to/detailed-error-messages).
Ustaw `MaxDegreeOfParallelism` na `Environment.ProcessorCount`, aby dopasować do liczby rdzeni CPU. Użycie dodatkowych wątków zwiększa obciążenie i nie poprawia wydajności, szczególnie w przypadku modeli ML wymagających dużej mocy obliczeniowej procesora.
---
## Łączenie przetwarzania asynchronicznego i równoległego
Dla wysokoprzepustowych kolejek połącz `SemaphoreSlim` z `Task.WhenAll`, aby ograniczyć współbieżność. W przeciwieństwie do `Parallel.ForEach`, ten wzorzec utrzymuje I/O w trybie nieblokującym, jednocześnie kontrolując liczbę jednoczesnych dekodowań, zapobiegając nasyceniu puli wątków przy dużych obciążeniach.
### Dane wejściowe
Cztery z dwudziestu testowych obrazów kodów QR przetworzonych przez współbieżną kolejkę. Każdy obraz koduje URL i jest dekodowany równolegle przy użyciu ograniczonej współbieżności przez `SemaphoreSlim`.
<div class="competitors-section__wrapper-even-1">
<div class="competitors__card" style="width: 47%;">
<img src="/static-assets/qr/how-to/async-and-multithreading/input-pipeline-qr-1.webp"
alt="Obraz wejściowy kodu QR w potoku 1 z 20"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
Zdjęcie 1 (Potok 1 z 20)
</p>
</div>
<div class="competitors__card" style="width: 47%;">
<img src="/static-assets/qr/how-to/async-and-multithreading/input-pipeline-qr-2.webp"
alt="Obraz wejściowy kodu QR w potoku 2 z 20"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
Zdjęcie 2 (Pipeline 2 z 20)
</p>
</div>
</div>
<div class="competitors-section__wrapper-even-1">
<div class="competitors__card" style="width: 47%;">
<img src="/static-assets/qr/how-to/async-and-multithreading/input-pipeline-qr-3.webp"
alt="Obraz wejściowy kodu QR w potoku 3 z 20"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
Zdjęcie 3 (Pipeline 3 z 20)
</p>
</div>
<div class="competitors__card" style="width: 47%;">
<img src="/static-assets/qr/how-to/async-and-multithreading/input-pipeline-qr-4.webp"
alt="Obraz wejściowy kodu QR w potoku 4 z 20"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
Zdjęcie 4 (Pipeline 4 z 20)
</p>
</div>
</div>
```cs
:path=/static-assets/qr/content-code-examples/how-to/async-and-multithreading/semaphore-pipeline.cs
```
### Wynik
Po zakończeniu działania potoku konsola wyświetla podsumowanie: łączną liczbę zdekodowanych kodów QR, liczbę plików źródłowych i czas, który upłynął, a następnie nazwę każdego pliku i jego zdekodowany adres URL.
<div class="content-img-align-center">
<div class="center-image-wrapper">
<img src="/static-assets/qr/how-to/async-and-multithreading/test3async-output.webp" alt="Wynik działania programu wyświetlany w terminalu: 20 kodów QR z 20 plików z odkodowanym adresem URL dla każdego pliku" class="img-responsive add-shadow" />
</div>
</div>
[Pobierz wszystkie 20 obrazów testowych z kodami QR (high-volume-qr-images.zip).](/static-assets/qr/how-to/async-and-multithreading/high-volume-qr-images.zip)
Dostosuj limit semaforów do dostępnej liczby rdzeni w celu uzyskania przepustowości lub zmniejsz go, gdy obciążenie pamięci stanowi problem w przypadku dużych obrazów.
---
## Więcej informacji
- [Przykład skanowania ML](https://ironsoftware.com/csharp/qr/examples/read-qr-with-machine-learning/): porównanie trybów skanowania z przykładami kodu.
- [Instrukcja odczytu kodów QR](https://ironsoftware.com/csharp/qr/how-to/read-qr-codes-from-image/): budowa wejścia i podstawowe wzorce odczytu.
- [Samouczek dotyczący generatora kodów QR](https://ironsoftware.com/csharp/qr/tutorials/csharp-qr-code-generator/): generowanie z zastosowaniem stylów.
- [Dokumentacja API QrReader](https://ironsoftware.com/csharp/qr/object-reference/api/IronQr.QrReader.html): sygnatury metod i uwagi.
- [Dokumentacja API QrWriter](https://ironsoftware.com/csharp/qr/object-reference/api/IronQr.QrWriter.html): wszystkie nadładowania funkcji write.
- [Poradnik obsługi błędów](/csharp/qr/how-to/detailed-error-messages): izolacja błędów na poziomie plików i wzorce rejestrowania.
[Zapoznaj się z opcjami licencyjnymi,](https://ironsoftware.com/csharp/qr/licensing/) gdy potok będzie gotowy do produkcji.
Skanowanie kodów QR w trybie jednowątkowym blokuje wątek wywołujący na czas dekodowania każdego obrazu.
W procedurze obsługi przycisku WPF powoduje to zawieszenie interfejsu użytkownika do czasu zakończenia dekodowania. W zadaniu wsadowym przetwarzającym setki obrazów pozostawia rdzenie procesora bezczynne, podczas gdy mogłyby one pracować równolegle. Metoda ReadAsync z IronQR przesyła poszczególne odczyty do zadania awaitable, a standardowa metoda Read działa z Parallel.ForEach i Task.WhenAll dla przepustowości wsadowej.
W niniejszym przewodniku pokazano, jak przetwarzać kody QR asynchronicznie, rozdzielać odczyty partii między rdzenie procesora oraz łączyć oba wzorce w przypadku potoków o dużej przepustowości.
Szybki start: Asynchroniczne przetwarzanie kodów QR
Załaduj obraz i poczekaj na zdekodowane wyniki bez blokowania wątku wywołującego.
1Install IronQR with NuGet Package Manager
PM > Install-Package IronQR
Install-Package IronQR
2Skopiuj i uruchom ten fragment kodu.
using IronQr;using IronSoftware.Drawing;var input = new QrImageInput(AnyBitmap.FromFile("ticket.png"));IEnumerable<QrResult> results = await new QrReader().ReadAsync(input);Console.WriteLine(results.First().Value);
using IronQr;
using IronSoftware.Drawing;
var input = new QrImageInput(AnyBitmap.FromFile("ticket.png"));
IEnumerable<QrResult> results = await new QrReader().ReadAsync(input);
Console.WriteLine(results.First().Value);
C#
3Wdrożenie do testowania w środowisku produkcyjnym
Użyj ReadAsync do nieblokujących odczytów pojedynczych
Użyj Parallel.ForEach do przetwarzania wsadowego obciążającego procesor
Połącz z SemaphoreSlim, aby uzyskać potoki o ograniczonej współbieżności
Zbierz wyniki z IEnumerable<QRRESULT> i wydrukuj zdekodowane wartości
Asynchroniczne odczytywanie kodów QR
ReadAsync zwraca zadanie awaitable, co czyni go kompatybilnym z obsługą zdarzeń WPF/MAUI, akcjami kontrolera ASP.NET lub dowolną metodą asynchroniczną. Dane wejściowe muszą być utworzone z bitmapy obrazu; nie ma przeciążenia ścieżki pliku.
Strona pisania jest synchroniczna i nie ma wariantów asynchronicznych. Aby uniknąć blokowania wątku podczas operacji I/O na plikach, otocz krok zapisywania w File.WriteAllBytesAsync() używając surowych bajtów eksportowanych z bitmapy.
Dane wejściowe
Identyfikator wydarzenia w postaci kodu QR zeskanowany i wygenerowany ponownie w celu zademonstrowania asynchronicznego wzorca odczytu i zapisu.
using IronQr;using IronQr.Enum;using IronSoftware.Drawing;// --- Async read: non-blocking QR decode ---var inputBmp = AnyBitmap.FromFile("event-badge.png");var imageInput = new QrImageInput(inputBmp, QrScanMode.Auto);var reader = new QrReader();IEnumerable<QrResult> results = await reader.ReadAsync(imageInput);foreach (QrResult result in results){Console.WriteLine($"[{result.QrType}] {result.Value}");}// --- Async-wrapped save: QrWriter.Write() and QrCode.Save() are synchronous ---QrCode qrCode = QrWriter.Write("https://ironsoftware.com");AnyBitmap qrImage = qrCode.Save();// Save the bitmap bytes asynchronously (not an IronQR API — standard .NET async I/O)byte[] pngBytes = qrImage.ExportBytes();awaitFile.WriteAllBytesAsync("output-qr.png", pngBytes);
using IronQr;
using IronQr.Enum;
using IronSoftware.Drawing;
// --- Async read: non-blocking QR decode ---
var inputBmp = AnyBitmap.FromFile("event-badge.png");
var imageInput = new QrImageInput(inputBmp, QrScanMode.Auto);
var reader = new QrReader();
IEnumerable<QrResult> results = await reader.ReadAsync(imageInput);
foreach (QrResult result in results)
{
Console.WriteLine($"[{result.QrType}] {result.Value}");
}
// --- Async-wrapped save: QrWriter.Write() and QrCode.Save() are synchronous ---
QrCode qrCode = QrWriter.Write("https://ironsoftware.com");
AnyBitmap qrImage = qrCode.Save();
// Save the bitmap bytes asynchronously (not an IronQR API — standard .NET async I/O)
byte[] pngBytes = qrImage.ExportBytes();
await File.WriteAllBytesAsync("output-qr.png", pngBytes);
C#
Wynik
Terminal wyświetla dekodowany typ QR i wartość w formacie [QrType] Value, a następnie potwierdza, że output-qr.png został zapisany.
QrScanMode.Auto uruchamia zarówno wykrywanie ML, jak i podstawowe skanowanie, wypełniając zdekodowaną wartość i typ QR w każdym wyniku. OnlyDetectionModel jest szybszy, ale zwraca tylko współrzędne pola ograniczającego, pozostawiając pole wartości puste. Użyj Auto zawsze, gdy potrzebna jest zakodowana treść.
Przetwarzanie kodów QR z wykorzystaniem wielowątkowości
Dla obrazów, które można dekodować niezależnie, Parallel.ForEach rozdziela pracę między dostępne rdzenie CPU. Oddzielna instancja QrReader na każdą iterację jest bezpiecznym domyślnym wyborem, ponieważ IronQR nie zapewnia wyraźnej gwarancji bezpieczeństwa wątków dla współdzielonych instancji czytników.
Dane wejściowe
Cztery z dziesięciu obrazów testowych kodów QR użytych w równoległym skanowaniu partii. Każdy obraz koduje URL i jest odczytywany z folderu qr-images/ w czasie wykonywania.
Zdjęcie 1 (partia 1 z 10)
Zdjęcie 2 (partia 2 z 10)
Zdjęcie 3 (partia 3 z 10)
Zdjęcie 4 (partia 4 z 10)
using IronQr;using IronQr.Enum;using IronSoftware.Drawing;using System.Collections.Concurrent;using System.Diagnostics;string[] files = Directory.GetFiles("qr-images/", "*.png");var allResults = new ConcurrentBag<(stringFile, stringValue)>();int failCount = 0;var sw = Stopwatch.StartNew();Parallel.ForEach(files, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, file =>{ try { var input = new QrImageInput(AnyBitmap.FromFile(file),QrScanMode.Auto); // Per-thread QrReader instance — safe default var results = new QrReader().Read(input); foreach (QrResult result in results) { allResults.Add((Path.GetFileName(file), result.Value)); } } catch (Exception ex) {Interlocked.Increment(ref failCount);Console.Error.WriteLine($"[ERROR] {Path.GetFileName(file)}: {ex.Message}"); }});sw.Stop();Console.WriteLine($"Processed {files.Length} files in {sw.Elapsed.TotalSeconds:F1}s");Console.WriteLine($"QR codes found: {allResults.Count} | Failures: {failCount}");Console.WriteLine($"Throughput: {files.Length / sw.Elapsed.TotalSeconds:F1} files/sec");
using IronQr;
using IronQr.Enum;
using IronSoftware.Drawing;
using System.Collections.Concurrent;
using System.Diagnostics;
string[] files = Directory.GetFiles("qr-images/", "*.png");
var allResults = new ConcurrentBag<(string File, string Value)>();
int failCount = 0;
var sw = Stopwatch.StartNew();
Parallel.ForEach(files, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, file =>
{
try
{
var input = new QrImageInput(
AnyBitmap.FromFile(file),
QrScanMode.Auto);
// Per-thread QrReader instance — safe default
var results = new QrReader().Read(input);
foreach (QrResult result in results)
{
allResults.Add((Path.GetFileName(file), result.Value));
}
}
catch (Exception ex)
{
Interlocked.Increment(ref failCount);
Console.Error.WriteLine($"[ERROR] {Path.GetFileName(file)}: {ex.Message}");
}
});
sw.Stop();
Console.WriteLine($"Processed {files.Length} files in {sw.Elapsed.TotalSeconds:F1}s");
Console.WriteLine($"QR codes found: {allResults.Count} | Failures: {failCount}");
Console.WriteLine($"Throughput: {files.Length / sw.Elapsed.TotalSeconds:F1} files/sec");
C#
Wynik
Konsola wyświetla podsumowanie partii, w tym liczbę przetworzonych plików, czas przetwarzania, znalezione kody QR, ewentualne błędy oraz przepustowość. Następnie podaje każdą nazwę pliku wraz z jego zdekodowanym adresem URL.
ConcurrentBag<t> zbiera wyniki ze wszystkich wątków bez potrzeby użycia blokad. Licznik bezpieczny dla wątków śledzi awarie, a użycie try-catch dla każdego pliku gwarantuje, że jeden uszkodzony obraz nie przerwie całej partii. Podejście to jest zgodne z wzorcem izolacji błędów opisanym w poradniku dotyczącym obsługi błędów.
Ustaw MaxDegreeOfParallelism na Environment.ProcessorCount, aby dopasować do liczby rdzeni CPU. Użycie dodatkowych wątków zwiększa obciążenie i nie poprawia wydajności, szczególnie w przypadku modeli ML wymagających dużej mocy obliczeniowej procesora.
Łączenie przetwarzania asynchronicznego i równoległego
Dla wysokoprzepustowych kolejek połącz SemaphoreSlim z Task.WhenAll, aby ograniczyć współbieżność. W przeciwieństwie do Parallel.ForEach, ten wzorzec utrzymuje I/O w trybie nieblokującym, jednocześnie kontrolując liczbę jednoczesnych dekodowań, zapobiegając nasyceniu puli wątków przy dużych obciążeniach.
Dane wejściowe
Cztery z dwudziestu testowych obrazów kodów QR przetworzonych przez współbieżną kolejkę. Każdy obraz koduje URL i jest dekodowany równolegle przy użyciu ograniczonej współbieżności przez SemaphoreSlim.
Zdjęcie 1 (Potok 1 z 20)
Zdjęcie 2 (Pipeline 2 z 20)
Zdjęcie 3 (Pipeline 3 z 20)
Zdjęcie 4 (Pipeline 4 z 20)
using IronQr;using IronQr.Enum;using IronSoftware.Drawing;using System.Collections.Concurrent;using System.Diagnostics;string[] files = Directory.GetFiles("high-volume/", "*.png");var results = new ConcurrentBag<(stringFile, stringValue)>();int maxConcurrency = Environment.ProcessorCount;using var semaphore = new SemaphoreSlim(maxConcurrency);var sw = Stopwatch.StartNew();var tasks = files.Select(async file =>{ await semaphore.WaitAsync(); try { var bmp = AnyBitmap.FromFile(file); // Auto: runs ML detection plus a basic scan so result.Value is populated var input = new QrImageInput(bmp, QrScanMode.Auto); var qrResults = await new QrReader().ReadAsync(input); foreach (var qr in qrResults) { results.Add((Path.GetFileName(file), qr.Value)); } } catch (Exception ex) {Console.Error.WriteLine($"{{\"file\":\"{Path.GetFileName(file)}\",\"error\":\"{ex.Message}\"}}"); } finally { semaphore.Release(); }});awaitTask.WhenAll(tasks);sw.Stop();Console.WriteLine($"Pipeline complete: {results.Count} QR codes from {files.Length} files in {sw.Elapsed.TotalSeconds:F1}s");
using IronQr;
using IronQr.Enum;
using IronSoftware.Drawing;
using System.Collections.Concurrent;
using System.Diagnostics;
string[] files = Directory.GetFiles("high-volume/", "*.png");
var results = new ConcurrentBag<(string File, string Value)>();
int maxConcurrency = Environment.ProcessorCount;
using var semaphore = new SemaphoreSlim(maxConcurrency);
var sw = Stopwatch.StartNew();
var tasks = files.Select(async file =>
{
await semaphore.WaitAsync();
try
{
var bmp = AnyBitmap.FromFile(file);
// Auto: runs ML detection plus a basic scan so result.Value is populated
var input = new QrImageInput(bmp, QrScanMode.Auto);
var qrResults = await new QrReader().ReadAsync(input);
foreach (var qr in qrResults)
{
results.Add((Path.GetFileName(file), qr.Value));
}
}
catch (Exception ex)
{
Console.Error.WriteLine($"{{\"file\":\"{Path.GetFileName(file)}\",\"error\":\"{ex.Message}\"}}");
}
finally
{
semaphore.Release();
}
});
await Task.WhenAll(tasks);
sw.Stop();
Console.WriteLine($"Pipeline complete: {results.Count} QR codes from {files.Length} files in {sw.Elapsed.TotalSeconds:F1}s");
C#
Wynik
Po zakończeniu działania potoku konsola wyświetla podsumowanie: łączną liczbę zdekodowanych kodów QR, liczbę plików źródłowych i czas, który upłynął, a następnie nazwę każdego pliku i jego zdekodowany adres URL.
Dostosuj limit semaforów do dostępnej liczby rdzeni w celu uzyskania przepustowości lub zmniejsz go, gdy obciążenie pamięci stanowi problem w przypadku dużych obrazów.
Czym jest asynchroniczne przetwarzanie kodu QR w C#?
Asynchroniczne przetwarzanie kodu QR w C# pozwala wykonywać operacje kodu QR bez blokowania głównego wątku, wykorzystując funkcje takie jak metoda ReadAsync IronQR, aby poprawić wydajność i responsywność.
Jak wielowątkowość może zwiększyć wydajność przetwarzania kodu QR?
Wielowątkowość może znacznie zwiększyć wydajność przetwarzania kodu QR, umożliwiając jednoczesne uruchamianie wielu operacji, co umożliwia szybsze czasy przetwarzania i poprawioną efektywność aplikacji z wykorzystaniem IronQR.
Czym jest metoda ReadAsync w IronQR?
Metoda ReadAsync w IronQR umożliwia asynchroniczne czytanie kodów QR, pozwalając twojej aplikacji C# obsługiwać dane kodu QR bez opóźniania innych zadań.
W jaki sposób Parallel.ForEach pomaga w przetwarzaniu kodów QR?
Parallel.ForEach umożliwia jednoczesne przetwarzanie wielu kodów QR przez rozdzielanie zadań na wiele wątków, które można efektywnie wykorzystać z IronQR, aby przyspieszyć operacje kodów QR.
Jaką rolę odgrywa SemaphoreSlim w operacjach kodu QR?
SemaphoreSlim jest używane do ograniczania liczby współbieżnych zadań, co pomaga efektywnie zarządzać zasobami podczas przetwarzania równoległego kodów QR z IronQR.
Czy można użyć IronQR do przetwarzania kodów QR w ograniczonym potoku?
Tak, IronQR można użyć do przetwarzania kodów QR w ograniczonym potoku, korzystając z konstrukcji takich jak SemaphoreSlim, aby skutecznie kontrolować współbieżność i alokację zasobów.
Jakie są korzyści z używania IronQR do asynchronicznych operacji kodu QR?
Użycie IronQR do operacji asynchronicznych kodu QR poprawia responsywność aplikacji, zmniejsza blokowanie na głównym wątku i pozwala na efektywne obsługiwanie dużych ilości danych kodu QR.
Czy można uruchamiać operacje kodu QR równolegle za pomocą IronQR?
Tak, IronQR obsługuje przetwarzanie równoległe operacji kodu QR, pozwalając wykorzystać możliwości wielowątkowości w C# do szybszej i bardziej wydajnej obsługi kodów QR.
W jaki sposób IronQR zwiększa przetwarzanie kodów QR w aplikacjach C#?
IronQR zwiększa przetwarzanie kodów QR poprzez dostarczanie solidnych możliwości asynchronicznych i wielowątkowych, co zmniejsza czas przetwarzania i poprawia skalowalność aplikacji C#.
Jakie funkcje C# uzupełniają użycie IronQR do przetwarzania kodów QR?
Funkcje C# takie jak async/await, Parallel.ForEach i SemaphoreSlim uzupełniają IronQR, zapewniając ramy dla efektywnego i wydajnego przetwarzania kodów QR.
Curtis Chau posiada tytuł licencjata z informatyki (Uniwersytet Carleton) i specjalizuje się w front-endowym rozwoju, z ekspertką w Node.js, TypeScript, JavaScript i React. Pasjonuje się tworzeniem intuicyjnych i estetycznie przyjemnych interfejsów użytkownika, Curtis cieszy się pracą z nowoczesnymi frameworkami i tworzeniem dobrze zorganizowanych, atrakcyjnych wizualnie podręczników.