求助大家
我有通过mshtml 来获得网页的元素集合IHTMLElementCollection(线程A)然后开辟一个线程来分析IHTMLElementCollection 中的元素 (线程B)
在(线程B) 处理的时候,(线程A)会继续获取网页元素
这个时候,我发现原本获取的网页元素值变化了(因为之前获取的是指针)有什么办法可以存储获取的IHTMLElement ??我想了些法子。。比如遍历属性保存。。但不能存储自定义属性,而且还耗费内存空间谢谢大家
我有通过mshtml 来获得网页的元素集合IHTMLElementCollection(线程A)然后开辟一个线程来分析IHTMLElementCollection 中的元素 (线程B)
在(线程B) 处理的时候,(线程A)会继续获取网页元素
这个时候,我发现原本获取的网页元素值变化了(因为之前获取的是指针)有什么办法可以存储获取的IHTMLElement ??我想了些法子。。比如遍历属性保存。。但不能存储自定义属性,而且还耗费内存空间谢谢大家
假设HTML源代码如下:
<html>
<body>
<input type="button" id="btnClose" value="关闭" />
</body>
</html>那么找出该按钮并为之添加Event Handler的代码如下:HtmlDocument htmlDoc = webBrowser.Document;
HtmlElement btnElement = htmlDoc.All["btnClose"];
if (btnElement != null)
{
btnElement.click += new HtmlElementEventHandler(HtmlBtnClose_Click);
}其中 HtmlBtnClose_Click是按下Web按钮时的Event Handler。很简单吧?那么稍稍高级一点的——我们都知道一个HTML元素可能有很多各种各样的事件,而HtmlElement这个类只给出最常用、共通的几个。那么,如何响应其他事件呢?这也很简单,只需要调用HtmlElement的AttachEventHandler就可以了:btnElement.AttachEventHandler("onclick", new EventHandler(HtmlBtnClose_Click));
//这一句等价于上面的 btnElement.click += new HtmlElementEventHandler(HtmlBtnClose_Click);对于其他事件,把"onclick"换成该事件的名字就可以了。例如:
formElement.AttachEventHandler("onsubmit", new EventHandler(HtmlForm_Submit));Study Case 2:表单(form)的自动填写和提交
要使我们的WebBrowser具有自动填表、甚至自动提交的功能,并不困难。假设有一个最简单的登录页面,输入用户名密码,点“登录”按钮即可登录。已知用户名输入框的id(或Name,下同)是username,密码输入框的id是password,“登录”按钮的id是submitbutton,那么我们只需要在webBrowser的 DocumentCompleted事件中使用下面的代码即可:HtmlElement btnSubmit = webBrowser.Document.All["submitbutton"];
HtmlElement tbUserid = webBrowser.Document.All["username"];
HtmlElement tbPasswd = webBrowser.Document.All["password"];
if (tbUserid == null || tbPasswd == null || btnSubmit == null)
return;
tbUserid.SetAttribute("value", "smalldust");
tbPasswd.SetAttribute("value", "12345678");
btnSubmit.InvokeMember("click");这里我们用SetAttribute来设置文本框的“value”属性,用InvokeMember来调用了按钮的“click”方法。因为不同的Html元素,其拥有的属性和方法也不尽相同,所以.Net 2.0提供了统一的HtmlElement来概括各种Html元素的同时,提供了这两个方法以调用元素特有的功能。关于各种Html元素的属性和方法一览,可以查阅MSDN的DHTML Reference。※关于表单的提交,的确还有另一种方法就是获取form元素而不是button,并用form元素的 submit方法:HtmlElement formLogin = webBrowser.Document.Forms["loginForm"];
//……
formLogin.InvokeMember("submit");本文之所以没有推荐这种方法,是因为现在的网页,很多都在submit按钮上添加onclick事件,以对提交的内容做最基本的验证。如果直接使用form的submit方法,这些验证代码就得不到执行,有可能会引起错误。
1、避免产生IE 缓存
2、加快载入速度(PS: 我是采用xmlhttp + mshtml 的方式, mshtml只是作为DOM 分析引擎在使用)
--- 我需要一天8调试,针对6个站点循环获取数据。
如果换用IE 对象,缓存可能会增多,加上加载图片的时间,速度会慢。
框架通过接口,可以来管理符合接口的程序(运行、计划任务运行、停止、错误通知、错误后尝试运行等等)然后这个项目是获取给定网址中所有的超级链接,然后保存超链接下列资料到数据库。
1、title
2、body
3、url再次感谢。
即使在STA下,有时还会出现我上面所说的莫名其妙变为空引用的情况,多半是GC造成的。
谢谢mshtml 是非托管代码,理论上mshtml 产生的对象不会被自动回收。而.NET 中存储mshtml 返回值的Array 等信息都没有被回收,只是被存储的IHTMLElement 中的数据被清空了。。
我期望的是,我想把mshtml 运行中产生的 Document 提取一个子对象(比如getElementsByTagName 返回的结果集)进行单独处理。 然后mshtml 还是继续执行自己的操作。。但看起来好像 Document 与 产生的结果集 是相互存在的, 结果集不能独立于Document 进行DOM 的访问操作。
.Net下的mshtml其实还是从Com中封装出来的。首先不保留Document对象,只保留具体的Element是肯定不行的,我感觉,Element里面实际保存的就是一个字符串的开始位置和结束位置,这个字符串就是整个Document对象的内容。另外LZ可以看一下,当Elements变为空的时候,其父级的Elements是否也已经是空了?或说整个Document都已经变为空了?
刚才调试结果: 从Elements 有值到无值 不会触发 Dispose 方法我想到个解决方法
首先,我不是通过mshtml get\post 站点,而是通过xmlhttp (虽然可以直接使用mshtml 访问站点,
但由于最初我是用VFP 写的COM(xmlhttp + ie 对象 ),然而在.NET 多线程调用的情况下,VFP Runtime 会产生C0000005 的Error 所以使用.NET 重写,为了尽可能利用原来的代码,所以还是保留了原来的设计方法。
)所以,mshtml 对我来说只是DOM 分析的一个框架。
联想到:我存储Elements 的时候,把页面的Document 也存储起来,
需要取值的时候把Document 恢复到mshtml 中。
有点感概,虽然用xmlhttp 获取数据有点绕路,但在这个方案感觉反而简单了
优点:
1,整个站点都通过一个xmlhttp 访问,不会因为获取Elements(采用Document 恢复到mshtml) 而造成数据的错误.
缺点:
1,可能因为存储了整个Document ,内存上可能会被增多。
不过方法能否行的通,还需要做测试,最近几天会回复结果。
是不是我的方法有错误?我在下列地方设置断点,但都没跑到1、在类的析构函数
2、Dispose 中不行就用前面说的笨方法了。
析构函数在回收时会被执行,但如果此时对象还被引用,GC就不会回收。
谢谢litaoye 一直回帖。 这个问题就此结束,等有时间了再深究唉,技术爱你不容易啊现实很残酷啊。。