C# ile QR Kod İşlemleri için Async ve Multithreading Nasıl Kullanılır
Tek iş parçacıklı QR taraması, her görüntü kod çözümü süresince çağırıcı iş parçacığını bloklar.
Bir WPF düğme işleyicisi içinde, bu, kullanıcı arayüzünü kod çözümü tamamlanana kadar dondurur. Yüzlerce görüntü işleyen toplu bir iş olarak, paralel çalışabilirlerken CPU çekirdeklerini boş bırakır. IronQR'nin ReadAsync yöntemi, bireysel okumaları beklenebilir bir göreve aktarır ve standart Read yöntemi, toplu işlemde Parallel.ForEach ve Task.WhenAll ile çalışır.
Bu rehber, QR kodlarını asenkron olarak nasıl işleyeceğinizi, toplu okumayı CPU çekirdekleri arasında nasıl dağıtacağınızı ve iki kalıbı yüksek hacimli hatlar için birleştireceğinizi gösterir.
Hızlı Başlangıç: QR Kodları Asenkron Olarak İşlemek
Bir görüntü yükleyin ve dekod işlemi sonucunu çağırıcı iş parçacığı bloklanmadan bekleyin.
-
NuGet Paket Yöneticisi ile https://www.nuget.org/packages/IronQR yükleyin
PM > Install-Package IronQR -
Bu kod parçasını kopyalayıp çalıştırın.
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); -
Canlı ortamınızda test etmek için dağıtın
Bugün projenizde IronQR kullanmaya başlayın ücretsiz deneme ile
Minimal İş Akışı (5 adımda)
- Asenkron QR kod işleme için IronQR C# kütüphanesini indirin
- Tek bloksuz okuma için
ReadAsynckullanın - CPU tabanlı toplu işleme için
Parallel.ForEachkullanın - Kod çözüm süreçleri için
SemaphoreSlimile sınırlı eşzamanlık hatlarını birleştirin - Sonuçları
IEnumerable<QrResult>ile toplayın ve kod çözüm değerlerini yazdırın
Asenkron Olarak QR Kodları Okumak
ReadAsync bir beklenebilir görev döndürür, bu da onu WPF/MAUI olay işleyicileri, ASP.NET denetleyici eylemleri veya herhangi bir eş zamanlı yöntemle uyumlu hale getirir. Girdi bir görüntü bitmap'inden oluşturulmalıdır; dosya yolu aşırı yüklemesi yoktur.
Yazma tarafı senkron ve asenkron varyantları yoktur. Dosya I/O işlemi sırasında iş parçacığını engellememek için, bitmap'ten dışa aktarılan ham baytları kullanarak kayıt adımını File.WriteAllBytesAsync() içinde sarın.
Girdi
Bir QR kodu etkinlik yaka karti tarandı ve asenkron okuma ve yazma deseni göstermek için tekrar oluşturuldu.
:path=/static-assets/qr/content-code-examples/how-to/async-and-multithreading/async-read-write.cs
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.OnlyDetectionModel);
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);
Imports IronQr
Imports IronQr.Enum
Imports IronSoftware.Drawing
Imports System.IO
' --- Async read: non-blocking QR decode ---
Dim inputBmp = AnyBitmap.FromFile("event-badge.png")
Dim imageInput = New QrImageInput(inputBmp, QrScanMode.OnlyDetectionModel)
Dim reader = New QrReader()
Dim results As IEnumerable(Of QrResult) = Await reader.ReadAsync(imageInput)
For Each result As QrResult In results
Console.WriteLine($"[{result.QrType}] {result.Value}")
Next
' --- Async-wrapped save: QrWriter.Write() and QrCode.Save() are synchronous ---
Dim qrCode As QrCode = QrWriter.Write("https://ironsoftware.com")
Dim qrImage As AnyBitmap = qrCode.Save()
' Save the bitmap bytes asynchronously (not an IronQR API — standard .NET async I/O)
Dim pngBytes As Byte() = qrImage.ExportBytes()
Await File.WriteAllBytesAsync("output-qr.png", pngBytes)
Çıktı
Terminal, kodlanmış QR türünü ve değerini [QrType] Value formatında gösterir, ardından output-qr.png kaydedildiğini onaylar.
QrScanMode.Auto hem ML algılamayı hem de temel bir tarama geçişini çalıştırır, her sonuçta kodlanmış değeri ve QR türünü doldurur. OnlyDetectionModel daha hızlıdır, ancak yalnızca sınır kutusu koordinatlarını döndürür ve değer alanını boş bırakır. Kodlanmış içerik gerektiğinde Auto kullanın.
Çok Işlemceli QR Kodlarını İşleme
Bağımsız olarak kodunu çözebilen görüntüler için, Parallel.ForEach işi mevcut CPU çekirdeklerine dağıtır. Her iterasyon başına ayrı bir QrReader örneği, güvenli varsayılan olarak kabul edilir, çünkü IronQR, paylaşılan okuyucu örnekleri için açık bir iş parçacığı güvenliği garantisi vermez.
Girdi
Paralel toplu taramada kullanılan on QR kod test görüntüsünden dördü. Her görüntü bir URL kodlar ve çalışma zamanında qr-images/ klasöründen okunur.
Görüntü 1 (Batch 1 of 10)
Görüntü 2 (Batch 2 of 10)
Görüntü 3 (Batch 3 of 10)
Görüntü 4 (Batch 4 of 10)
:path=/static-assets/qr/content-code-examples/how-to/async-and-multithreading/parallel-batch.cs
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.OnlyDetectionModel);
// 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");
Imports IronQr
Imports IronQr.Enum
Imports IronSoftware.Drawing
Imports System.Collections.Concurrent
Imports System.Diagnostics
Dim files As String() = Directory.GetFiles("qr-images/", "*.png")
Dim allResults As New ConcurrentBag(Of (File As String, Value As String))()
Dim failCount As Integer = 0
Dim sw As Stopwatch = Stopwatch.StartNew()
Parallel.ForEach(files, New ParallelOptions With {.MaxDegreeOfParallelism = Environment.ProcessorCount}, Sub(file)
Try
Dim input As New QrImageInput(AnyBitmap.FromFile(file), QrScanMode.OnlyDetectionModel)
' Per-thread QrReader instance — safe default
Dim results = New QrReader().Read(input)
For Each result As QrResult In results
allResults.Add((Path.GetFileName(file), result.Value))
Next
Catch ex As Exception
Interlocked.Increment(failCount)
Console.Error.WriteLine($"[ERROR] {Path.GetFileName(file)}: {ex.Message}")
End Try
End Sub)
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")
Çıktı
Konsol, işlenen dosya sayısı, işleme süresi, bulunan QR kodları, herhangi bir başarısızlık ve verimi kapsayan bir toplu özet görüntüler. Ardından, her dosya adı ve kod çözülmüş URL'siyle birlikte bir liste görüntüler.
10 test toplu QR kod girdi görüntüsunu indirin (batch-qr-images.zip).
ConcurrentBag<T>, tüm iş parçacıklarından sonuçları kilit gerektirmeden toplar. İş parçacığı güvenli bir sayaç başarısızlıkları izler ve her dosya için try-catch kullanmak, bir bozuk görüntünün tüm topluyu kesintiye uğratmamasını sağlar. Bu yaklaşım, hata işleme nasıl yapılır bölümünde açıklanan hata izolasyon desenini uygular.
MaxDegreeOfParallelism'ı CPU çekirdek sayısına uyumlu olacak şekilde Environment.ProcessorCount olarak ayarlayın. Ek iplikler kullanmak, yükü artırır ve özellikle CPU yoğun ML modelleri için performansı iyileştirmez.
Async ve Paralel İşlemeyi Kombin Etmek
Yüksek hacimli hatlar için, eşzamanlılığı sınırlamak için SemaphoreSlim ile Task.WhenAll eşleştirin. Parallel.ForEach'un aksine, bu düzen I/O'yu engellemeden tutar ve bir anda kaç çözümlemenin çalışacağını kontrol ederek büyük iş yükleri altında iş parçacığı havuzu doyumunu önler.
Girdi
Eş zamanlı hat yoluyla işlenen yirmi QR kodu test görüntüsünden dört tanesi. Her görüntü bir URL kodlar ve SemaphoreSlim aracılığıyla sınırlandırılmış eşzamanlılık kullanılarak paralel olarak çözülür.
Görüntü 1 (Pipe 1 of 20)
Görüntü 2 (Pipe 2 of 20)
Görüntü 3 (Pipe 3 of 20)
Görüntü 4 (Pipe 4 of 20)
:path=/static-assets/qr/content-code-examples/how-to/async-and-multithreading/semaphore-pipeline.cs
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);
// OnlyDetectionModel: fastest per-image — critical at scale
var input = new QrImageInput(bmp, QrScanMode.OnlyDetectionModel);
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");
Imports IronQr
Imports IronQr.Enum
Imports IronSoftware.Drawing
Imports System.Collections.Concurrent
Imports System.Diagnostics
Module Program
Sub Main()
Dim files As String() = Directory.GetFiles("high-volume/", "*.png")
Dim results As New ConcurrentBag(Of (File As String, Value As String))()
Dim maxConcurrency As Integer = Environment.ProcessorCount
Using semaphore As New SemaphoreSlim(maxConcurrency)
Dim sw As Stopwatch = Stopwatch.StartNew()
Dim tasks = files.Select(Function(file) Task.Run(Async Function()
Await semaphore.WaitAsync()
Try
Dim bmp = AnyBitmap.FromFile(file)
' OnlyDetectionModel: fastest per-image — critical at scale
Dim input As New QrImageInput(bmp, QrScanMode.OnlyDetectionModel)
Dim qrResults = Await (New QrReader()).ReadAsync(input)
For Each qr In qrResults
results.Add((Path.GetFileName(file), qr.Value))
Next
Catch ex As Exception
Console.Error.WriteLine($"{{""file"":""{Path.GetFileName(file)}"",""error"":""{ex.Message}""}}")
Finally
semaphore.Release()
End Try
End Function))
Task.WhenAll(tasks).Wait()
sw.Stop()
Console.WriteLine($"Pipeline complete: {results.Count} QR codes from {files.Length} files in {sw.Elapsed.TotalSeconds:F1}s")
End Using
End Sub
End Module
Çıktı
Hat tamamlandığında konsol bir özet görüntüler: toplam QR kodları çözümlenen, kaynak dosya sayısını ve geçen süreyi, ardından her dosya adı ve kod çözümlenen URL'siyle birlikte.
20 test hat QR kodu girdi görüntüsunu indirin (high-volume-qr-images.zip).
Getiri için semafor limitini kullanılabilir çekirdek sayısına uydurun veya büyük görsellerle bellek yükü endişesi olduğunda düşürün.
Daha Fazla Okuma
- ML Tarama Örneği: tarama modu karşılaştırması ve kod örnekleri.
- QR Kodlarını Nasıl Okunur: girdi yapımı ve temel okuma kalıpları.
- QR Kodu Üretici Eğitimi: stil ile üretim.
- QrReader API Referansı: yöntem imzaları ve notlar.
- QrWriter API Referansı: tüm yazma yükleri.
- Hata İşleme Nasıl Yapılır: dosya bazlı hata izolasyonu ve günlükleme kalıpları.
Boru hattı üretim için hazır olduğunda lisanslama seçeneklerini görüntüleyin.

