现在,我正在使用puppeteer(NodeJS库)将HTML转换为PDF文档。尽管这是“有效的”,但我正在移植到Puppeteer-Sharp(C#库)。
一切正常,但我有点担心同时运行多个浏览器。
例如,我在同一台计算机上的两个单独的进程中运行相同的代码:
// Magic function. Downloads Chrome to a specific directory for the process.
var browser = GetBrowser();
var page = await browser.NewPageAsync();
await page.GoToAsync("http://www.google.com");
var pdf = await page.PdfAsync();
我的问题:
这里是否存在潜在的并发问题?
我的(有限的)理解是该库使用websocket向Chrome发布了指令,并且我不确定浏览器是否有可能彼此“冲突”。
基本上,我在问是否有可能(通过await page.PdfAsync();
接收到的PDF字节来自“其他”浏览器。
如果有什么安慰的话,浏览器会在每个进程中从特定目录下载并启动,因此从技术上讲,它不是两次启动Chrome的“相同”实例(但实际上是这样)。
答案 0 :(得分:0)
您不需要多个浏览器,可以将一个浏览器与多个选项卡(或“伪娘”称呼的页面)一起使用。这是我的示例代码,可以解决您所做的相同事情(将HTML转换为PDF)。 它创建一个浏览器实例,该实例被简化为四个进程(可能更多),每个进程创建并删除自己的Page。
public class PuppeteerSharpSample {
public async Task CreatePdfBatch(IEnumerable<string> urlList)
{
await using var browser = await Puppeteer.LaunchAsync( new LaunchOptions { Headless = true, ExecutablePath ="PathToChromeOrChromium.exe"};).ConfigureAwait(false);
await urlList.ForEachAsync(4, async url =>
{
await PrintPdf(url, browser).ConfigureAwait(false);
})
.ContinueWith(t =>
{
if (t.Exception != null)
{
throw t.Exception;
}
})
.ConfigureAwait(false);
}
private async Task PrintPdf(Browser browser, string Url)
{
await using var page = await browser.NewPageAsync().ConfigureAwait(false);
await page.GoToAsync(url).ConfigureAwait(false);
await page.PdfAsync("pdfFileNameMustBeMadeUniqueOfCourse.pdf").ConfigureAwait(false);
}
}
public static class HelperClass
{
//taken from https://scatteredcode.net/parallel-foreach-async-in-c/
public static Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body)
{
async Task AwaitPartition(IEnumerator<T> partition)
{
using (partition)
{
while (partition.MoveNext())
{
await body(partition.Current).ContinueWith(t =>
{
if (t.IsFaulted && t.Exception != null)
{
throw t.Exception;
}
})
.ConfigureAwait(false);
}
}
}
return Task.WhenAll(
Partitioner
.Create(source)
.GetPartitions(dop)
.AsParallel()
.Select(AwaitPartition));
}
}
请注意:如果您的计算机上安装了Chromium(可以是Chrome,Chromium或新的Edge),则也不需要使用GetBrowser()
。然后,您只需指向上面的代码中所示的.exe即可。