如何在 C# 中使用异步和多线程进行二维码操作 Copy for LLMsCopy for LLMs Copy page as Markdown for LLMs
# 如何在 C# 中使用异步和多线程进行二维码操作
单线程二维码扫描会在每次图像解码期间阻塞调用线程。
在 WPF 按钮处理程序中,这将冻结 UI,直到解码完成。 在批量处理数百张图像时,CPU 核心会闲置,而它们本可以并行工作。 IronQR的`Task.WhenAll`一起工作以提高批量吞吐量。
本指南演示了如何异步处理二维码、将批量读取任务分配到 CPU 内核上,以及如何将这两种模式结合起来以实现高容量流水线。
*as-heading:2(快速入门:异步处理二维码)*
加载图像并等待解码结果,而不阻塞调用线程。
```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# 库,实现异步二维码处理</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>
## 异步读取二维码
`ReadAsync`返回一个可等待的任务,使其与WPF/MAUI事件处理程序、ASP.NET控制器操作或任何异步方法兼容。 输入必须由图像位图构成;不支持文件路径重载。
写入端是同步的,没有异步变体。 为了避免在文件I/O期间阻塞线程,请在`File.WriteAllBytesAsync()`中使用从位图导出的原始字节包裹保存步骤。
### 输入
扫描并重新生成二维码活动徽章,以演示异步读写模式。
<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="二维码编码 https://ironsoftware.com/event-badge 用作异步读取输入"
class="img-responsive add-shadow" />
</div>
</div>
```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.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);
```
### 输出
终端显示经过解码的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`。
---
## 使用多线程处理二维码
对于可以独立解码的图像,`Parallel.ForEach`会将工作分配给可用的CPU核心。 每次迭代使用一个单独的`QrReader`实例是安全的默认设置,因为IronQR对共享读取器实例没有明确的线程安全保证。
### 输入
并行批量扫描中使用的十个二维码测试图像中有四个。 每个图像编码一个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="批量二维码输入图像 1/10,编码 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="批量二维码输入图像 2/10,编码 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="批量二维码输入图像 3/10,编码 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="批量二维码输入图像 4/10,编码 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(共 10 张,第 4 张)
</p>
</div>
</div>
```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.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");
```
### 输出
控制台显示批处理摘要,包括已处理的文件数、处理时间、找到的二维码、任何故障和吞吐量。 然后它会列出每个文件名及其解码后的 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 个文件,已找到二维码,存在失败,吞吐量为 [数量],每个文件名已解码 URL" class="img-responsive add-shadow" />
</div>
</div>
[下载全部 10 个测试批次的二维码输入图像(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 密集型机器学习模型而言。
---
## 结合异步和并行处理
对于大批量流水线,将`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="管道二维码输入图像,第 1 张(共 20 张)"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
图 1(共 20 道流程中的第 1 道)
</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="管道二维码输入图像,第 2 张(共 20 张)"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
图 2(20 个流程中的第 2 个)
</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="管道二维码输入图像,第 3 张(共 20 张)"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
图 3(共 20 道流程中的第 3 道)
</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="管道二维码输入图像,第 4 张(共 20 张)"
class="img-responsive add-shadow" style="max-width: 200px;" />
<p class="competitors__download-link" style="color: #181818; font-style: italic;">
图 4(共 20 道流程中的第 4 道)
</p>
</div>
</div>
```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);
// 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");
```
### 输出
控制台会在管道完成后显示摘要:解码的二维码总数、源文件数量和经过的时间,以及每个文件名及其解码后的 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 个二维码,每个文件名都包含解码后的 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/):扫描模式与代码示例的比较。
-[如何读取二维码](https://ironsoftware.com/csharp/qr/how-to/read-qr-codes-from-image/):输入结构和基本读取模式。
-[二维码生成器教程](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
单线程二维码扫描会在每次图像解码期间阻塞调用线程。
在 WPF 按钮处理程序中,这将冻结 UI,直到解码完成。 在批量处理数百张图像时,CPU 核心会闲置,而它们本可以并行工作。 IronQR的Task.WhenAll一起工作以提高批量吞吐量。
本指南演示了如何异步处理二维码、将批量读取任务分配到 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# 库,实现异步二维码处理 使用ReadAsync进行非阻塞式单次读取 使用 Parallel.ForEach 进行 CPU 密集型批处理 与 SemaphoreSlim 结合使用,构建有界并发管道 从IEnumerable<QrResult>中收集结果并打印解码后的值
异步读取二维码
ReadAsync返回一个可等待的任务,使其与WPF/MAUI事件处理程序、ASP.NET控制器操作或任何异步方法兼容。 输入必须由图像位图构成;不支持文件路径重载。
写入端是同步的,没有异步变体。 为了避免在文件I/O期间阻塞线程,请在File.WriteAllBytesAsync()中使用从位图导出的原始字节包裹保存步骤。
输入
扫描并重新生成二维码活动徽章,以演示异步读写模式。
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。
使用多线程处理二维码
对于可以独立解码的图像,Parallel.ForEach会将工作分配给可用的CPU核心。 每次迭代使用一个单独的QrReader实例是安全的默认设置,因为IronQR对共享读取器实例没有明确的线程安全保证。
输入
并行批量扫描中使用的十个二维码测试图像中有四个。 每个图像编码一个URL,并在运行时从qr-images/文件夹中读取。
图片 1(第 1 批,共 10 批)
图片 2(第 2 批,共 10 张)
图片 3(第 3 批,共 10 批)
图片 4(共 10 张,第 4 张)
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#
输出
控制台显示批处理摘要,包括已处理的文件数、处理时间、找到的二维码、任何故障和吞吐量。 然后它会列出每个文件名及其解码后的 URL。
下载全部 10 个测试批次的二维码输入图像(batch-qr-images.zip)。
ConcurrentBag<t>收集所有线程的结果,而不需要锁定。 线程安全的计数器会跟踪故障,并且对每个文件使用 try-catch 可以确保一个错误的图像不会中断整个批次。 这种方法遵循错误处理指南 中描述的错误隔离模式。
将Environment.ProcessorCount,以与CPU核心数量对齐。 使用额外的线程会增加开销,并且不会提高性能,特别是对于 CPU 密集型机器学习模型而言。
结合异步和并行处理
对于大批量流水线,将Task.WhenAll配对使用,以限制并发。 与Parallel.ForEach不同,此模式保持I/O非阻塞,同时控制同时运行的解码数量,防止在大工作负载下线程池饱和。
输入
并发管道处理的二十张QR码测试图像中的四张。每个图像编码一个URL,并通过SemaphoreSlim使用有限的并发方式并行解码。
图 1(共 20 道流程中的第 1 道)
图 2(20 个流程中的第 2 个)
图 3(共 20 道流程中的第 3 道)
图 4(共 20 道流程中的第 4 道)
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#
输出
控制台会在管道完成后显示摘要:解码的二维码总数、源文件数量和经过的时间,以及每个文件名及其解码后的 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#应用程序的可扩展性。
C#特性如async/await、Parallel.ForEach和SemaphoreSlim补充了IronQR,提供了高效高性能的QR码处理框架。
技术作家
Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。
...
阅读更多