如何在C#中使用非同步和多執行緒進行QR碼操作 Copy for LLMsCopy for LLMs Copy page as Markdown for LLMs
# 如何在C#中使用非同步和多執行緒進行QR碼操作
單執行緒QR掃描會在每次圖像解碼期間阻塞呼叫執行緒。
在WPF按鈕處理程式中,這將會凍結UI,直到解碼完成。 在處理數百張圖像的批次工作中,當CPU核心可以並行工作時,則會處於閒置狀態。 IronQR的`Task.WhenAll`批量吞吐量。
本指南演示了如何非同步處理QR碼,分配批量讀取到CPU核心,並結合這兩種模式以實現高容量流水線。
*as-heading:2(快速入門:非同步處理QR碼)*
載入圖片並在不阻塞呼叫執行緒的情況下等待解碼結果。
```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>最小化工作流程(共5步)</h3>
<ol>
<li><a class="js-modal-open" data-modal-id="trial-license-after-download" href="https://nuget.org/packages/IronQR/">下載IronQR C#程式庫以進行非同步QR碼處理</a></li>
<li>使用<code>ReadAsync</code>進行非阻塞的單次讀取</li>
<li>使用<code>Parallel.ForEach</code>進行CPU密集的批量處理</li>
<li>與<code>SemaphoreSlim</code>結合以實現有限併發流水線</li>
<li>從<code>IEnumerable<QrResult></code>中收集結果並列印解碼值</li>
</ol>
</div>
## 以非同步方式讀取QR碼
`ReadAsync`返回一個可等待的任務,使其可以與WPF/MAUI事件處理程式、ASP.NET控制器動作或任何非同步方法相容。 輸入必須從圖像位圖構建,沒有文件路徑的重載。
寫入方是同步的,沒有非同步變體。 為避免在文件I/O期間阻塞執行緒,使用從位圖導出的原始字節將保存步驟包裝在`File.WriteAllBytesAsync()`中。
### 輸入
掃描並重新生成的QR碼事件徽章,以展示非同步讀寫模式。
<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="QR碼編碼https://ironsoftware.com/event-badge作為非同步讀取輸入"
class="img-responsive add-shadow" />
</div>
</div>
```cs
:path=/static-assets/qr/content-code-examples/how-to/async-and-multithreading/async-read-write.cs
```
### 輸出
終端顯示解碼的QR型別和值格式`output-qr.png`已保存。
<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="終端輸出顯示[QRCode]解碼值和output-qr.png保存確認" class="img-responsive add-shadow" />
</div>
</div>
`QrScanMode.Auto`同時運行ML檢測和基本掃描,填充每個結果中的解碼值和QR型別。 `OnlyDetectionModel`速度更快,但僅返回邊框座標,值字段留空。 需要編碼內容時使用`Auto`。
---
## 使用多執行緒處理QR碼
對於可以獨立解碼的圖像,`Parallel.ForEach`分配工作到可用的CPU核心。 每次迭代一個單獨的`QrReader`實例是安全的預設值,因為IronQR沒有明確的執行緒安全保證。
### 輸入
平行批次掃描中用於測試的十張QR碼圖像中的四張。 每張圖片編碼一個URL,並在運行時從`qr-images/`文件夾中讀取。
<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="批次 QR code 輸入影像 10 張中的第 1 張,編碼 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;">
圖像1 (批次1,共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="批次 QR code 輸入影像 10 張中的第 2 張,編碼 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;">
圖像2 (批次2,共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="批次 QR code 輸入影像 10 張中的第 3 張,編碼 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;">
圖像3 (批次3,共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="批次 QR code 輸入影像 10 張中的第 4 張,編碼 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;">
圖像4 (批次4,共10批)
</p>
</div>
</div>
```cs
:path=/static-assets/qr/content-code-examples/how-to/async-and-multithreading/parallel-batch.cs
```
### 輸出
控制台顯示批次摘要,包括處理的文件數、處理時間、找到的QR碼、任何失敗和吞吐量。 然後列出每個文件名及其解碼的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="終端輸出顯示平行批次結果:已處理10個文件,找到的QR碼,失敗,吞吐量,以及每個文件名解碼的URL" class="img-responsive add-shadow" />
</div>
</div>
[下載所有10個測試批次QR碼輸入圖像 (batch-qr-images.zip)。](/static-assets/qr/how-to/async-and-multithreading/batch-qr-images.zip)
`ConcurrentBag<t>`從所有執行緒中收集結果,而不需要鎖定。 一個執行緒安全的計數器追蹤失敗,並使用try-catch保護每個文件,確保一個壞圖像不會中斷整個批次。 此方法遵循[錯誤處理指南](/csharp/qr/how-to/detailed-error-messages)中描述的錯誤隔離模式。
將`Environment.ProcessorCount`以對齊CPU核心數。 使用額外的執行緒會增加開銷且不提高性能,尤其是對於CPU密集型ML模型。
---
## 結合非同步和平行處理
對於高容量流水線,使用`Task.WhenAll`配對以限制併發性。 這種模式不同於`Parallel.ForEach`,保持I/O非阻塞,同時控制同時運行的解碼數,防止在大量工作負荷下執行緒池飽和。
### 輸入
處理併發流水線中的二十張QR碼測試圖像中的四張。每個圖像都編碼了URL,並通過`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="管線 QR 碼輸入影像,第 1 張,共 20 張"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
圖像1 (流水線1,共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="管線 QR 碼輸入影像,第 2 張,共 20 張"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
圖像2 (流水線2,共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="管線 QR 碼輸入影像,第 3 張,共 20 張"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
圖像3 (流水線3,共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="管線 QR 碼輸入影像,第 4 張,共 20 張"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
圖像4 (流水線4,共20)
</p>
</div>
</div>
```cs
:path=/static-assets/qr/content-code-examples/how-to/async-and-multithreading/semaphore-pipeline.cs
```
### 輸出
當流水線完成後,控制台顯示摘要:總計解碼的QR碼數量、源文件數量和經過時間,隨後是每個文件名及其解碼的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="終端輸出顯示流水線結果:從20個文件中解碼的20個QR碼,每個文件名解碼的URL" class="img-responsive add-shadow" />
</div>
</div>
[下載所有20個測試流水線QR碼輸入圖像 (high-volume-qr-images.zip)。](/static-assets/qr/how-to/async-and-multithreading/high-volume-qr-images.zip)
將信號閘限制與可用核心數匹配以提高吞吐量,或在大型圖像下記憶體壓力成為問題時降低。
---
## 進一步閱讀
- [ML掃描範例](https://ironsoftware.com/csharp/qr/examples/read-qr-with-machine-learning/):掃描模式比較與程式碼範例。
- [如何讀取QR碼](https://ironsoftware.com/csharp/qr/how-to/read-qr-codes-from-image/):輸入構建和基本讀取模式。
- [QR碼生成器教程](https://ironsoftware.com/csharp/qr/tutorials/csharp-qr-code-generator/):生成與樣式設計。
- [QrReader API參考](https://ironsoftware.com/csharp/qr/object-reference/api/IronQr.QrReader.html):方法簽名與備註。
- [QrWriter API參考](https://ironsoftware.com/csharp/qr/object-reference/api/IronQr.QrWriter.html):所有寫入重載。
- [錯誤處理指南](/csharp/qr/how-to/detailed-error-messages):每個文件的錯誤隔離與日誌記錄模式。
[檢視授權選項](https://ironsoftware.com/csharp/qr/licensing/),當流水線準備好進入生產時。
Ask ChatGPT about this page
Ask Gemini about this page
Ask Perplexity about this page
單執行緒QR掃描會在每次圖像解碼期間阻塞呼叫執行緒。
在WPF按鈕處理程式中,這將會凍結UI,直到解碼完成。 在處理數百張圖像的批次工作中,當CPU核心可以並行工作時,則會處於閒置狀態。 IronQR的Task.WhenAll批量吞吐量。
本指南演示了如何非同步處理QR碼,分配批量讀取到CPU核心,並結合這兩種模式以實現高容量流水線。
載入圖片並在不阻塞呼叫執行緒的情況下等待解碼結果。
1 Install IronQR with NuGet Package Manager
PM > Install-Package IronQR
Install-Package IronQR
2 複製並運行這段程式碼片段。
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#
3 部署以在您的實時環境中測試
今天就開始在您的專案中使用IronQR,透過免費試用
免費30天試用
最小化工作流程(共5步) 下載IronQR C#程式庫以進行非同步QR碼處理 使用ReadAsync進行非阻塞的單次讀取 使用Parallel.ForEach進行CPU密集的批量處理 與SemaphoreSlim結合以實現有限併發流水線 從IEnumerable<QrResult>中收集結果並列印解碼值
以非同步方式讀取QR碼
ReadAsync返回一個可等待的任務,使其可以與WPF/MAUI事件處理程式、ASP.NET控制器動作或任何非同步方法相容。 輸入必須從圖像位圖構建,沒有文件路徑的重載。
寫入方是同步的,沒有非同步變體。 為避免在文件I/O期間阻塞執行緒,使用從位圖導出的原始字節將保存步驟包裝在File.WriteAllBytesAsync()中。
輸入
掃描並重新生成的QR碼事件徽章,以展示非同步讀寫模式。
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);
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#
輸出
終端顯示解碼的QR型別和值格式output-qr.png已保存。
QrScanMode.Auto同時運行ML檢測和基本掃描,填充每個結果中的解碼值和QR型別。 OnlyDetectionModel速度更快,但僅返回邊框座標,值字段留空。 需要編碼內容時使用Auto。
使用多執行緒處理QR碼
對於可以獨立解碼的圖像,Parallel.ForEach分配工作到可用的CPU核心。 每次迭代一個單獨的QrReader實例是安全的預設值,因為IronQR沒有明確的執行緒安全保證。
輸入
平行批次掃描中用於測試的十張QR碼圖像中的四張。 每張圖片編碼一個URL,並在運行時從qr-images/文件夾中讀取。
圖像1 (批次1,共10批)
圖像2 (批次2,共10批)
圖像3 (批次3,共10批)
圖像4 (批次4,共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 <( 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" );
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#
輸出
控制台顯示批次摘要,包括處理的文件數、處理時間、找到的QR碼、任何失敗和吞吐量。 然後列出每個文件名及其解碼的URL。
下載所有10個測試批次QR碼輸入圖像 (batch-qr-images.zip)。
ConcurrentBag<t>從所有執行緒中收集結果,而不需要鎖定。 一個執行緒安全的計數器追蹤失敗,並使用try-catch保護每個文件,確保一個壞圖像不會中斷整個批次。 此方法遵循錯誤處理指南 中描述的錯誤隔離模式。
將Environment.ProcessorCount以對齊CPU核心數。 使用額外的執行緒會增加開銷且不提高性能,尤其是對於CPU密集型ML模型。
結合非同步和平行處理
對於高容量流水線,使用Task.WhenAll配對以限制併發性。 這種模式不同於Parallel.ForEach,保持I/O非阻塞,同時控制同時運行的解碼數,防止在大量工作負荷下執行緒池飽和。
輸入
處理併發流水線中的二十張QR碼測試圖像中的四張。每個圖像都編碼了URL,並通過SemaphoreSlim以有限併發進行平行解碼。
圖像1 (流水線1,共20)
圖像2 (流水線2,共20)
圖像3 (流水線3,共20)
圖像4 (流水線4,共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 <( 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" );
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#
輸出
當流水線完成後,控制台顯示摘要:總計解碼的QR碼數量、源文件數量和經過時間,隨後是每個文件名及其解碼的URL。
下載所有20個測試流水線QR碼輸入圖像 (high-volume-qr-images.zip)。
將信號閘限制與可用核心數匹配以提高吞吐量,或在大型圖像下記憶體壓力成為問題時降低。
進一步閱讀
檢視授權選項 ,當流水線準備好進入生產時。
常見問題 C#中的非同步QR碼處理允許您在不堵塞主執行緒的情況下進行QR碼操作,利用IronQR的ReadAsync方法來提升性能和響應性。
多執行緒可以顯著提高QR碼處理,允許多個操作同時運行,通過使用IronQR來加快處理時間並提高應用程式效率。
IronQR中的ReadAsync方法允許非同步讀取QR碼,使您的C#應用程式在處理QR碼資料時不會延遲其他任務。
Parallel.ForEach允許通過將任務分配到多個執行緒來同時處理多個QR碼,能夠高效利用IronQR加速QR碼操作。
SemaphoreSlim用於限制並行任務的數量,幫助在使用IronQR進行QR碼的並行處理時有效管理資源。
是的,IronQR可以用於在限定的管道中處理QR碼,使用如SemaphoreSlim等構建來有效控制併發和資源分配。
使用IronQR進行非同步QR碼操作可以提高應用程式的響應能力,減少主執行緒的阻塞,並能有效處理大量的QR碼資料。
是的,IronQR支持QR碼操作的並行處理,允許您在C#中利用多執行緒的能力,進行更快速和更高效的QR碼處理。
IronQR通過提供強大的非同步和多執行緒能力來增強QR碼處理,減少處理時間並提高C#應用程式的擴展性。
如async/await、Parallel.ForEach和SemaphoreSlim等C#功能,補充了IronQR提供高效和高性能的QR碼處理框架。
技術作家
Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。
...
閱讀更多