gpt4 book ai didi

c# - 我应该如何使用多线程正确调用 Web 浏览器?

转载 作者:行者123 更新时间:2023-11-30 17:05:16 24 4
gpt4 key购买 nike

问题范围:

我正在编写一个应用程序来保存从 BingGoogle 搜索中检索到的 HTML。我知道有一些类可以使用 this example 等流来执行 Web 请求,但是由于 Google 和 Bing 都使用 Javascript 和 Ajax 将结果呈现为 HTML,所以我无法简单地读取流并使用 get 获取结果我需要。

对此的解决方案是使用 WebBrowser 类并导航到我想要的 url,以便浏览器本身将处理所有 Javascript 和 Ajax 脚本执行。

多线程:

为了提高效率,我使用相同的表单应用程序为每个服务触发一个线程(一个用于 Bing,一个用于 Google)。

问题:

因为我需要 WebBrowser,所以我为每个线程实例化了一个(目前是 2 个)。根据 Microsoft 的说法,存在一个已知错误,如果 WebBrowser 不可见且未添加到可见表单,该错误会阻止 DocumentCompleted 事件触发(有关更多信息,请访问 follow this link)。

真正的问题:

主要问题是,浏览器的 DocumentCompleted 事件永远不会触发。从来没有。

我已经为从未获得回调的 DocumentCompleted 事件编写了一个适当的处理程序。为了处理触发浏览器事件所需的等待时间,我实现了一个具有高超时(5 分钟)的 AutoResetEvent,如果它在 5 分钟后没有触发我需要的事件,它将处理 webbrowser 线程。

目前,我已创建浏览器并将其添加到 WindowsForm 中,两者都是可见的,但事件仍未触发。

部分代码:

        // Creating Browser Instance
browser = new WebBrowser ();

// Setting up Custom Handler to "Document Completed" Event
browser.DocumentCompleted += DocumentCompletedEvent;

// Setting Up Random Form
genericForm = new Form();
genericForm.Width = 200;
genericForm.Height = 200;
genericForm.Controls.Add (browser);
browser.Visible = true;

至于导航我有以下(浏览器的方法):

    public void NavigateTo (string url)
{
CompletedNavigation = false;

if (browser.ReadyState == WebBrowserReadyState.Loading) return;

genericForm.Show (); // Shows the form so that it is visible at the time the browser navigates
browser.Navigate (url);
}

而且,对于导航的调用,我有这个:

            // Loading URL
browser.NavigateTo(URL);

// Waiting for Our Event To Fire
if (_event.WaitOne (_timeout))
{
// Success
}
{ // Error / Timeout From the AutoResetEvent }

TL:DR:

我的 WebBrowser 被实例化到另一个 STAThread 中,添加到表单中,两者都可见并在浏览器导航触发时显示,但浏览器的 DocumentCompleted 事件从未触发,因此 AutoResetEvent 总是超时,我没有响应从浏览器。

提前致谢,抱歉发了这么长的帖子

最佳答案

虽然这看起来很奇怪,但这是我的尝试。

var tasks = new Task<string>[]
{
new MyDownloader().Download("http://www.stackoverflow.com"),
new MyDownloader().Download("http://www.google.com")
};

Task.WaitAll(tasks);
Console.WriteLine(tasks[0].Result);
Console.WriteLine(tasks[1].Result);

public class MyDownloader
{
WebBrowser _wb;
TaskCompletionSource<string> _tcs;
ApplicationContext _ctx;
public Task<string> Download(string url)
{
_tcs = new TaskCompletionSource<string>();

var t = new Thread(()=>
{
_wb = new WebBrowser();
_wb.ScriptErrorsSuppressed = true;
_wb.DocumentCompleted += _wb_DocumentCompleted;
_wb.Navigate(url);
_ctx = new ApplicationContext();
Application.Run(_ctx);
});

t.SetApartmentState(ApartmentState.STA);
t.Start();

return _tcs.Task;
}

void _wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//_tcs.TrySetResult(_wb.DocumentText);
_tcs.TrySetResult(_wb.DocumentTitle);
_ctx.ExitThread();
}
}

关于c# - 我应该如何使用多线程正确调用 Web 浏览器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16715620/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com