异步代码并不比同步版本快
Asynchronous Code Is Not Faster than the Synchronous Version
我对异步编程不是很有经验,所以请原谅我的无知。
我正在尝试异步生成 PDFS 列表以提高性能。
然而,无论是异步还是同步,代码运行起来都是一样的:
Parallel Test MS: 10452
Async Test MS: 9971
Sync Test MS: 10501
有什么明显的地方我做错了吗,还是图书馆?我正在使用以下文档:https://ironpdf.com/docs/questions/async/
主要:
static async Task Main(string[] args)
{
var html = @"<h1>Hello World!</h1><br><p>This is IronPdfss.</p>";
Stopwatch stopwatch = new Stopwatch();
List<PdfDocument> pdfDocuments = new List<PdfDocument>();
List<string> htmlStrings = new List<string>();
for (int i = 0; i < iterations; i++)
htmlStrings.Add(html);
stopwatch.Start();
Parallel.ForEach(htmlStrings, htmlString =>
{
var document = RenderPdf(htmlString);
pdfDocuments.Add(document);
});
stopwatch.Stop();
Console.WriteLine($"Parallel Test MS: {stopwatch.ElapsedMilliseconds}");
stopwatch.Restart();
var tasks = htmlStrings.Select(async h =>
{
var response = await RenderPdfAsync(h);
pdfDocuments.Add(response);
});
await Task.WhenAll(tasks);
stopwatch.Stop();
Console.WriteLine($"Async Test MS: {stopwatch.ElapsedMilliseconds}");
stopwatch.Restart();
foreach (string h in htmlStrings)
{
var document = RenderPdf(h);
pdfDocuments.Add(document);
}
stopwatch.Stop();
Console.WriteLine($"Sync Test MS: {stopwatch.ElapsedMilliseconds}");
Console.ReadLine();
}
辅助方法:
private static async Task<IronPdf.PdfDocument> RenderPdfAsync(string Html, IronPdf.PdfPrintOptions PrintOptions = null)
{
return await Task.Run(() => RenderPdf(Html, PrintOptions));
}
private static IronPdf.PdfDocument RenderPdf(string Html, IronPdf.PdfPrintOptions PrintOptions = null)
{
var Renderer = new IronPdf.HtmlToPdf();
if (PrintOptions != null)
{
Renderer.PrintOptions = PrintOptions;
}
PdfDocument Pdf = Renderer.RenderHtmlAsPdf(Html);
return Pdf;
}
看这里:
var tasks = htmlStrings.Select(async h =>
{
var response = await RenderPdfAsync(h);
pdfDocuments.Add(response);
});
await Task.WhenAll(tasks);
您正在等待Select
,所以您一次只做一个。尝试做这样的事情:
var tasks = htmlStrings.Select(h =>
{
return RenderPdfAsync(h);
});
await Task.WhenAll(tasks);
foreach(var t in tasks){ pdfDocuments.Add(await t); }
请记住,您已经在上面使用了适当的并行库 (Parallel.ForEach
),为了保持一致,您也应该在这里使用该模式。
这一行
var response = await RenderPdfAsync(h);
应该是这样的
var task = RenderPdfAsync(h);
然后一起等待所有任务
private static async Task<IronPdf.PdfDocument> RenderPdfAsync(string Html, IronPdf.PdfPrintOptions PrintOptions = null)
{
return await Task.Run(() => RenderPdf(Html, PrintOptions));
}
这就是通常所说的“伪异步”。这是一种带有异步签名的方法,但实际上并不是异步的。它只是线程池线程上的同步工作 运行。因此,“异步”代码的行为与并行代码非常相似:它 运行 每个都在线程池线程上呈现。
在这种情况下,操作是 CPU 绑定的,而不是 I/O-bound,因此同步或并行代码是正确的方法。例如,我认为并行 LINQ 是最好的方法。你不想在这里使用异步代码。
你的计时有什么奇怪的是并行代码并不比同步代码快。对此的一种解释是 PDF 呈现已经 并行,因此额外的并行性无济于事。另一种解释是,某些东西限制您的应用程序只能在单个 CPU 内核上 运行ning。
截至 2021 年 9 月 - IronPDF 的 2021.9 版本在并行性方面比以往任何时候都好得多。
真正的多线程在 Web 和桌面应用程序开发方面对我的团队来说效果很好。
这个版本在 nuget 上可用:https://www.nuget.org/packages/IronPdf/
在 IronPdf 版本 2021.9.3737 上测试....
C# & VB 代码示例:
IronPDF + 异步:https://ironpdf.com/examples/async/
IronPDF + System.Threading : https://ironpdf.com/examples/threading/
IronPDF + Parallel.ForEach : https://ironpdf.com/examples/parallel/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IronPdf;
var Renderer = new IronPdf.ChromePdfRenderer();
var htmls = new List<string>() { "<h1>Html#1</h1>", "<h1>Html#2</h1>", "<h1>Html#3</h1>" };
Parallel.ForEach(htmls, (html) =>
{
var pdfDocument = Renderer.RenderHtmlAsPdfAsync(html).Result;
// do something with each pdfDocument
});
我对异步编程不是很有经验,所以请原谅我的无知。
我正在尝试异步生成 PDFS 列表以提高性能。
然而,无论是异步还是同步,代码运行起来都是一样的:
Parallel Test MS: 10452
Async Test MS: 9971
Sync Test MS: 10501
有什么明显的地方我做错了吗,还是图书馆?我正在使用以下文档:https://ironpdf.com/docs/questions/async/
主要:
static async Task Main(string[] args)
{
var html = @"<h1>Hello World!</h1><br><p>This is IronPdfss.</p>";
Stopwatch stopwatch = new Stopwatch();
List<PdfDocument> pdfDocuments = new List<PdfDocument>();
List<string> htmlStrings = new List<string>();
for (int i = 0; i < iterations; i++)
htmlStrings.Add(html);
stopwatch.Start();
Parallel.ForEach(htmlStrings, htmlString =>
{
var document = RenderPdf(htmlString);
pdfDocuments.Add(document);
});
stopwatch.Stop();
Console.WriteLine($"Parallel Test MS: {stopwatch.ElapsedMilliseconds}");
stopwatch.Restart();
var tasks = htmlStrings.Select(async h =>
{
var response = await RenderPdfAsync(h);
pdfDocuments.Add(response);
});
await Task.WhenAll(tasks);
stopwatch.Stop();
Console.WriteLine($"Async Test MS: {stopwatch.ElapsedMilliseconds}");
stopwatch.Restart();
foreach (string h in htmlStrings)
{
var document = RenderPdf(h);
pdfDocuments.Add(document);
}
stopwatch.Stop();
Console.WriteLine($"Sync Test MS: {stopwatch.ElapsedMilliseconds}");
Console.ReadLine();
}
辅助方法:
private static async Task<IronPdf.PdfDocument> RenderPdfAsync(string Html, IronPdf.PdfPrintOptions PrintOptions = null)
{
return await Task.Run(() => RenderPdf(Html, PrintOptions));
}
private static IronPdf.PdfDocument RenderPdf(string Html, IronPdf.PdfPrintOptions PrintOptions = null)
{
var Renderer = new IronPdf.HtmlToPdf();
if (PrintOptions != null)
{
Renderer.PrintOptions = PrintOptions;
}
PdfDocument Pdf = Renderer.RenderHtmlAsPdf(Html);
return Pdf;
}
看这里:
var tasks = htmlStrings.Select(async h =>
{
var response = await RenderPdfAsync(h);
pdfDocuments.Add(response);
});
await Task.WhenAll(tasks);
您正在等待Select
,所以您一次只做一个。尝试做这样的事情:
var tasks = htmlStrings.Select(h =>
{
return RenderPdfAsync(h);
});
await Task.WhenAll(tasks);
foreach(var t in tasks){ pdfDocuments.Add(await t); }
请记住,您已经在上面使用了适当的并行库 (Parallel.ForEach
),为了保持一致,您也应该在这里使用该模式。
这一行
var response = await RenderPdfAsync(h);
应该是这样的
var task = RenderPdfAsync(h);
然后一起等待所有任务
private static async Task<IronPdf.PdfDocument> RenderPdfAsync(string Html, IronPdf.PdfPrintOptions PrintOptions = null)
{
return await Task.Run(() => RenderPdf(Html, PrintOptions));
}
这就是通常所说的“伪异步”。这是一种带有异步签名的方法,但实际上并不是异步的。它只是线程池线程上的同步工作 运行。因此,“异步”代码的行为与并行代码非常相似:它 运行 每个都在线程池线程上呈现。
在这种情况下,操作是 CPU 绑定的,而不是 I/O-bound,因此同步或并行代码是正确的方法。例如,我认为并行 LINQ 是最好的方法。你不想在这里使用异步代码。
你的计时有什么奇怪的是并行代码并不比同步代码快。对此的一种解释是 PDF 呈现已经 并行,因此额外的并行性无济于事。另一种解释是,某些东西限制您的应用程序只能在单个 CPU 内核上 运行ning。
截至 2021 年 9 月 - IronPDF 的 2021.9 版本在并行性方面比以往任何时候都好得多。
真正的多线程在 Web 和桌面应用程序开发方面对我的团队来说效果很好。
这个版本在 nuget 上可用:https://www.nuget.org/packages/IronPdf/
在 IronPdf 版本 2021.9.3737 上测试....
C# & VB 代码示例:
IronPDF + 异步:https://ironpdf.com/examples/async/
IronPDF + System.Threading : https://ironpdf.com/examples/threading/
IronPDF + Parallel.ForEach : https://ironpdf.com/examples/parallel/
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using IronPdf; var Renderer = new IronPdf.ChromePdfRenderer(); var htmls = new List<string>() { "<h1>Html#1</h1>", "<h1>Html#2</h1>", "<h1>Html#3</h1>" }; Parallel.ForEach(htmls, (html) => { var pdfDocument = Renderer.RenderHtmlAsPdfAsync(html).Result; // do something with each pdfDocument });