C# ile QR Kod İşlemleri için Async ve Multithreading Nasıl Kullanılır

This article was translated from English: Does it need improvement?
Translated
View the article in English

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.

  1. NuGet Paket Yöneticisi ile https://www.nuget.org/packages/IronQR yükleyin

    PM > Install-Package IronQR
  2. 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);
  3. Canlı ortamınızda test etmek için dağıtın

    Bugün projenizde IronQR kullanmaya başlayın ücretsiz deneme ile

    arrow pointer

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.

https://ironsoftware.com/event-badge üzerinden QR kodu kodlaması asenkron okuma girdisi olarak kullanıldı
: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)
$vbLabelText   $csharpLabel

Çıktı

Terminal, kodlanmış QR türünü ve değerini [QrType] Value formatında gösterir, ardından output-qr.png kaydedildiğini onaylar.

QR değeri kodu ve output-qr.png kayıt onayını çözümlenmiş olarak gösteren terminal çıktısı

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.

Batch QR code input image 1 of 10 encoding https://ironsoftware.com/batch-1
Batch QR code input image 2 of 10 encoding https://ironsoftware.com/batch-2
Batch QR code input image 3 of 10 encoding https://ironsoftware.com/batch-3
Batch QR code input image 4 of 10 encoding https://ironsoftware.com/batch-4
: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")
$vbLabelText   $csharpLabel

Çı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.

Paralel toplu sonuçları gösteren terminal çıktısı: 10 dosya işlenmiş, QR kodları bulunmuş, hatalar, verim ve her dosya adına kod çözülmüş URL

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.

Pipeline QR code input image 1 of 20
Pipeline QR code input image 2 of 20
Pipeline QR code input image 3 of 20
Pipeline QR code input image 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
$vbLabelText   $csharpLabel

Çı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.

Boru hattı sonucunu gösteren terminal çıktısı: 20 dosyadan 20 QR kodu ve her dosya adına kod çözülmüş URL

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

Boru hattı üretim için hazır olduğunda lisanslama seçeneklerini görüntüleyin.

Curtis Chau
Teknik Yazar

Curtis Chau, Bilgisayar Bilimleri alanında lisans derecesine sahiptir (Carleton Üniversitesi) ve Node.js, TypeScript, JavaScript ve React konularında uzmanlaşmış ön uç geliştirme üzerine uzmanlaşmıştır. Kullanıcı dostu ve estetik açıdan hoş arayüzler tasarlamaya tutkuyla bağlı olan Curtis, modern çerç...

Daha Fazlasını Oku
Başlamaya Hazır mısınız?
Nuget İndirmeler 64,787 | Sürüm: 2026.4 just released
Still Scrolling Icon

Hala Kaydiriyor musunuz?

Hızlı bir kanit mi istiyorsunuz? PM > Install-Package IronQR
bir örneği çalıştır URL'inin bir QR koduna dönüşünü izle.