关于多线程下调用mshtml的IMarkupServices的问题

绿色夹克衫 2009-08-11 11:09:24
最近经常用到mshtml,出于效率的考虑,需要使用IMarkupServices来解析html,
单一线程下没有问题,但在使用多线程的时候,问题来了,调用COM时经常会出现问题。

查了一下资料,应该是STAThread的问题,IMarkupServices泡在MTA模式下会有问题,于是放弃了线程池,回过头来改用Thread,
并用Thread.SetApartmentState(ApartmentState.STA);将线程设为了STA模式,不过问题仍然没有从根上解决,有时还会出现问题。

不知道诸位高手有谁了解这个问题,有什么好的解决方案?
...全文
191 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
fan_mvp 2012-02-26
  • 打赏
  • 举报
回复
12333333333333
绿色夹克衫 2009-08-13
  • 打赏
  • 举报
回复
这是我修改过的解析部分的程序,这部分跑起来似乎没有什么问题,但是后面遍历返回的
IHTMLDocument2 时,有时会变为空,不知道是否因为两个指针被回收造成的?

因为每次的情况都不太一样,但有时候会变为空,不太好找究竟是哪里的错误。
感觉像是被回收了,另外这样的错误主要出现在解析大网页的时候。

public static IHTMLDocument2 HtmlParseNoScript(string htmlContent)
{
IHTMLDocument2 pDocument = new HTMLDocumentClass();

if (pDocument == null)
return null;

IPersistStreamInit pPersist = pDocument as IPersistStreamInit;
pPersist.InitNew();
IMarkupServices ms = pDocument as IMarkupServices;

if (ms == null)
return null;

IMarkupContainer pMC = null;
IMarkupPointer pStart, pEnd;
ms.CreateMarkupPointer(out pStart);
ms.CreateMarkupPointer(out pEnd);

IntPtr pSource = Marshal.StringToHGlobalUni(htmlContent);
unsafe { ms.ParseString(ref *(ushort*)pSource.ToPointer(), 0, out pMC, pStart, pEnd); }

Marshal.Release(pSource);

if (pMC == null)
return null;

return pMC as IHTMLDocument2;
}
绿色夹克衫 2009-08-13
  • 打赏
  • 举报
回复
to:bigmingming

非常感谢你的回答,不过我的问题并没有解决,首先需要解决的是,在遍历IMarkupServices 返回的 IHTMLDocument2时,有时IHTMLDocument2会莫名其妙的变为空,我觉得应该是跟.net的垃圾回收有关。
济南大飞哥 2009-08-12
  • 打赏
  • 举报
回复
我爱多线程
guyehanxinlei 2009-08-12
  • 打赏
  • 举报
回复
友情帮顶
超维电脑科技 2009-08-12
  • 打赏
  • 举报
回复
友情顶
绿色夹克衫 2009-08-12
  • 打赏
  • 举报
回复
顶一下,改为单线程发现也有问题,似乎是遍历IHTMLDocument2.all 之后出现的问题,
自己写了个递归去遍历,发现也有问题。
bigmingming 2009-08-12
  • 打赏
  • 举报
回复
http://rc.org.cn/1/viewspace-351
bigmingming 2009-08-12
  • 打赏
  • 举报
回复
先参考一下http://www.wangchao.net.cn/bbsdetail_73175.html
makun0624 2009-08-11
  • 打赏
  • 举报
回复
学习` UP
绿色夹克衫 2009-08-11
  • 打赏
  • 举报
回复
仔细查了一下,似乎不是IMarkupServices解析的问题,如果使用
Thread.SetApartmentState(ApartmentState.STA),似乎都可以得到正确的解析结果,但返回后的处理,有时会莫名其妙的得不到IHTMLDocument2,个人感觉应该跟Com调用有关。
chaozi_249 2009-08-11
  • 打赏
  • 举报
回复
mark
xxxxxchener 2009-08-11
  • 打赏
  • 举报
回复
up!
绿色夹克衫 2009-08-11
  • 打赏
  • 举报
回复
to:ls

这个帖子里面的程序解决的是IMarkupServices解析的问题,但如果直接放入线程里面跑,在多线程下应该会出问题。
bigmingming 2009-08-11
  • 打赏
  • 举报
回复
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using mshtml;
using System.Diagnostics;
using System.Runtime.InteropServices.ComTypes;

namespace HTMLDocumentTest
{
[ComVisible(true), ComImport(), Guid( "7FD52380-4E07-101B-AE2D-08002B2EC713 "), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPersistStreamInit
{
void GetClassID([In, Out] ref Guid pClassID);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int IsDirty();
void Load([In, MarshalAs(UnmanagedType.Interface)] IStream pstm);
void Save([In, MarshalAs(UnmanagedType.Interface)] IStream pstm,
[In, MarshalAs(UnmanagedType.I4)] int fClearDirty);
void GetSizeMax([Out, MarshalAs(UnmanagedType.LPArray)] long pcbSize);
void InitNew();
}
class Program
{
[STAThread]
static void Main(string[] args)
{
Parse( " <HTML> </HTML> ");
}
public static unsafe IHTMLDocument2 Parse(string s)
{
IHTMLDocument2 pDocument=new HTMLDocumentClass();
if(pDocument!=null)
{
IPersistStreamInit pPersist=(IPersistStreamInit)pDocument;
pPersist.InitNew();
IMarkupServices ms=(IMarkupServices)pDocument;
if(ms != null)
{
Console.WriteLine( "success ");
}
}
return pDocument;
}
}
}
bigmingming 2009-08-11
  • 打赏
  • 举报
回复
http://www.host01.com/article/Net/00020007/0652316020470995.htm
绿色夹克衫 2009-08-11
  • 打赏
  • 举报
回复
自己顶一下,不知道是否和Com销毁对象有关。本来获取的值是正常的,执行到后面就突然变为空了!

110,499

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧