单线程没问题,多线程出问题

chenzhichao2008 2008-08-06 11:17:32
大家好,请各位高手帮忙看一下,谢谢!


如果程序调用Go(url,depth)
可以运行

如果改用多线程,调用Run(url,depth)
就会出错

工程设置:debug multiThreaded dll


bool CEngine::GetSourceHtml( const CString &theUrl, CStringBuf &buf )
{
CInternetFile* file = NULL;
CInternetSession session; //当执行这个一句时,theUrl值竟然被改变了
CString str;
try
{
// 试着连接到指定URL
file = (CInternetFile*) session.OpenURL(theUrl);
}
catch (CInternetException* m_pException)
{
m_pException->Delete();
return false;
}
buf.m_buf="";
while( file->ReadString(str) != NULL )
{
buf.m_buf+=str;
}
buf.m_language = HTML_LAN_CHINESE;
return true;
}

void CEngine::Run(const CString &url, int depth)
{
SetUrlAndDepth(url,depth);
CloseHandle( CreateThread(NULL, 0, Go2, (LPVOID)this, 0, NULL) );
}

DWORD WINAPI CEngine::Go2( LPVOID lpParam )
{
CEngine *g = (CEngine*) lpParam;
g->Go(g->m_url, g->m_depth);
AfxMessageBox(_T("complete"));
return 1;
}

bool CEngine::Go(const CString &url, int depth)
{
CComPtr<IDispatch> spDispatch;
MSHTML::IHTMLDocument2Ptr pDoc;
CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> pDoc2;
CComPtr<IHTMLElementCollection> pElementCol;
CComPtr<IHTMLAnchorElement> pLoct;
CStringBuf buf;
MSHTML::IHTMLElementCollectionPtr pCollection;
MSHTML::IHTMLElementPtr pElement;

if( depth <= 0 || !m_hash.Insert((LPCSTR)url) )
return false;

if( !GetSourceHtml(url, buf) )
return false;
pDoc = GetDocument(buf);
...
}
...全文
192 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
formajia5 2008-09-25
  • 打赏
  • 举报
回复
支持下
formajia5 2008-09-25
  • 打赏
  • 举报
回复
受教了,继续阿楼主
majiajun_no_3 2008-09-25
  • 打赏
  • 举报
回复
分析得精彩.....
formajia3 2008-09-24
  • 打赏
  • 举报
回复
很受益!
lehedele 2008-09-24
  • 打赏
  • 举报
回复
潜水多年,今日上岸,继续学习
chenzhichao2008 2008-08-06
  • 打赏
  • 举报
回复
主要错误是 bool CEngine::GetSourceHtml( const CString &theUrl, CStringBuf &buf )
的theUrl值被CInternetSession session;语句改了

如果只是调用Go,而不是调用run,就不会出现问题
也就是没有另开一个新线程,程序是没问题的
chenzhichao2008 2008-08-06
  • 打赏
  • 举报
回复
在程序开始已经有调用CoInitialize(NULL);
chenzhichao2008 2008-08-06
  • 打赏
  • 举报
回复
不好意思,让大家久等了,刚才去吃饭了
声明部份 static DWORD WINAPI Go2( LPVOID lpParam );


CInternetSession session; //当执行这个一句时,theUrl值竟然被改变了,改成乱西八糟的东西,要能是theUrl
被释放了

有时调试错误还是发生在:
可以确定m_hash.Insert((LPCSTR)url)代码没问题

if( depth <= 0 || !m_hash.Insert((LPCSTR)url) )
return false;


yayafu 2008-08-06
  • 打赏
  • 举报
回复
初始化com库试试
kakashi0309 2008-08-06
  • 打赏
  • 举报
回复
问题不明确
scq2099yt 2008-08-06
  • 打赏
  • 举报
回复
能否贴出错误信息?
ouyh12345 2008-08-06
  • 打赏
  • 举报
回复
啥问题?
cnzdgs 2008-08-06
  • 打赏
  • 举报
回复
m_url被释放了吧?
chenzhichao2008 2008-08-06
  • 打赏
  • 举报
回复
CloseHandle( CreateThread(NULL, 0, Go2, (LPVOID)&g_engine, 0, NULL) );
chenzhichao2008 2008-08-06
  • 打赏
  • 举报
回复
嗯,问题找出来了,谢谢你们

有两个错误:一个是每个线程必须都初始化com
一个是
CloseHandle( CreateThread(NULL, 0, Go2, (LPVOID)this, 0, NULL) );
这里this不是全局对象,没办法实现线程之间的数据共享
CEngine g_engine;

CloseHandle( CreateThread(NULL, 0, Go2, (LPVOID)&engine, 0, NULL) );

这样就可以了


结贴:)
stivenjia 2008-08-06
  • 打赏
  • 举报
回复
CoInitialize(NULL);线程内初始化
CoInitializeEx我记得MSCOM有个这个东西能设定COM访问模型。
jameshooo 2008-08-06
  • 打赏
  • 举报
回复
Go2线程也必须执行CoInitialize(NULL)/CoUninitialize(),COM初始化必须每线程独立调用
cnzdgs 2008-08-06
  • 打赏
  • 举报
回复
你可以在Go2中先显示一个MessageBox,接下来设置一个断点,查看m_url,估计这时就应该出问题了。如果没出问题,就继续单步调试,同时注意m_url的变化;如果MessageBox后已经出现问题,检查一下主线程在创建线程之后做了哪些操作,注意一下在m_url之前定义的数组是否存在访问越界。

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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