【发布时间】:2015-12-15 00:13:58
【问题描述】:
我在处理来自外部类的线程时遇到问题。我在线程方面还很陌生,所以很多事情对我来说仍然是个谜,所以请记住这一点。
我进行了研究,发现了许多关于它的主题,包括:
- How to Sleep a thread until callback for asynchronous function is received?
- https://www.youtube.com/watch?v=xaaRBh07N34
而且看起来很清楚,但仍然对我没有帮助。这是我的代码:
public DownloadContent()
{
adres = @"...";
wb = new WebBrowser();
wb.Navigating += (object sender, WebBrowserNavigatingEventArgs e) => objWait.WaitOne();
wb.DocumentCompleted += (object sender, WebBrowserDocumentCompletedEventArgs e) => objWait.Set(); //Here is the problem
wb.DocumentCompleted += OnDocumentCompleted;
wb.Navigate(adres);
MessageBox.Show("after"); //should print after OnDocumentCompleted
}
private void OnDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//some logic
}
问题是这个 WebBrowser 类使用单独的线程来导航和完成文档。这没有什么问题,但我不知道我的主线程应该如何与之通信。我试图让原始线程等待,但存在一个问题,即假设再次启动它的函数 objWait.Set() 被当前冻结的主线程调用。我认为这是真正的问题。我尝试了许多奇怪的方法来使它起作用:
- 为 wb.Navigate(...) 创建另一个线程;它不起作用,因为它不能在单线程上工作;
- 为 objWait.Set() 单独创建线程;也没用,不知道为什么;
- 还有一些更奇怪的东西。
我知道这对某些人来说可能微不足道,但我已经坚持了好几个小时了,我真的不知道该怎么办。因此,我将不胜感激。
************************************************编辑*** ************************************************
谢谢大家的回答。我看到很多人注意到我最初的问题并给了我一些建议,我很感激,你让我的工作更轻松。话虽这么说,这个任务的本质是找出是否有任何处理它的好方法。无论如何,感谢您的所有建议和指导,一旦我完成了这个小项目(当时只有一件事),我会仔细研究它们。
我想我可以这样做:
public DownloadContent()
{
...
bool flag = true;
wb.DocumentCompleted += OnDocumentCompleted;
wb.DocumentCompleted += (object sender, WebBrowserDocumentCompletedEventArgs e) => flag = false;
wb.Navigate(adres);
while(flag);
MessageBox.Show("after"); //should print after OnDocumentCompleted
}
但我不知道这是否被认为是有效或优雅的解决方案。如果您对此有任何想法,我将不胜感激。提前谢谢你。
【问题讨论】:
-
您是要下载网页的 HTML 还是要渲染页面以供打印或类似的东西?
-
我想从网站获取一些信息。我遵循本指南中的第一种方法:link 我使用 wb 因为我需要访问 元素。
-
文章还展示了
WebClient和“HtmlAgilityPack”的使用。如果您需要访问 HTML 源代码并提取数据,这就是您要走的路。如果你这样做,代码是单线程的并且非常快。 -
WebBrowser 不能在任何线程上工作,你必须创建一个特殊的。一个线程,它是 STA 并实现了 STA 合约。这需要泵送一个消息循环(Application.Run)并且绝不能阻塞。违反 STA 合同会导致死锁并阻止 WebBrowser 引发任何事件,这是您发现的那种麻烦。一旦你有了一个 STA 线程,那么让它从你的主线程做一些事情就变得非常容易。示例代码is here.
标签: c# multithreading external autoresetevent