急,急,急,久,久,久,闷,闷,闷,DLL中创建线程的问题,大家就帮帮我吧,都进来讨论啊

appleing 2003-08-24 12:31:17
我想在dll里面创建线程,线程函数是dll内部的,创建函数也在dll内部的,

但是,为什么创建不起来,是不是我做错了什么,帮帮忙吧,有没有方法让我能够在dll里面创建并且执行线程的,这里高手多,我就靠大家了

代码如下:

void thread_code()
{
MessageBox("box","ok",MB_OK);
//这个框框一直不弹出来,按理说应该是10秒一个才对
//为什么会等到这个dll释放了,才弹出来,并且出错了
}

void begin()
{
for(int i=0;i<10;i++)
{
DWORD funid;
CreateThread(NULL, 0, thread_code, NULL, 0, &funid);
Sleep(10000);
}
}

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
switch(reason)
{
case DLL_PROCESS_ATTACH:
//DisbaleThreadLibraryCalls,见文后
begin();
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return 1;
}

这个是上次的问题,我经过多方询问,大概知道了原因.

但是,问题仍然不得解啊,也许是我太笨了,

也寻到一个方法,DisbaleThreadLibraryCalls函数,只是,这个函数一直调用失败,郁闷自今,而且,放在begin函数的调用前面,是防止dll重复创建线程的意思,真的是这样解决问题吗?

总之,我还是没有解决问题,希望各位高手有另外的良方,大家都看看吧.
...全文
84 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
appleing 2003-08-28
  • 打赏
  • 举报
回复
嗯,多谢季前辈,看来我对dll的了解还是不够,可以说是不会,不过,听了你的解释,

已经非常清楚了,这大概就和form的create函数一样,是一个东西创建的时候建立的,所以,里面执行某些功能是不行的(如form的create函数里面把窗体设为不可见),哈哈,明白了问题,果然舒服多了.

另外也感想以上所有回到我问题的朋友,感想behard,结贴了.
appleing 2003-08-27
  • 打赏
  • 举报
回复
不是这样的,我那个程序比较大,这些线程函数本来用在exe中是正常运行的.

后来,我的exe因为某些原因,不能再把一些创建线程的函数放在里面了...

然后,我就把exe中的某些线程的函数和建立线程的函数单独放在dll中运行,

结果就出现了这种情况,dll中不能创建线程.........................

我为了证明dll中确实不能创建线程,

于是写了上述的测试代码,结果如我预料一般...

我不是说dll中一定不能创建线程,只是,创建的方法特殊,我不懂..

如果dll中按照exe中的创建线程的方法(就如我上述代码),是绝对行不通的,线程不可能运行!

谢谢大家的帮忙,只是,情况确实如此,大家不信就试试,在dll中试试啊,我真的很需要答案的.

Behard 2003-08-27
  • 打赏
  • 举报
回复
看错了
我以为你的 begin 函数是在导出函数中调用的
(begin 函数如果在导出函数中是没有问题的,我就是这样测试的)

不过如果你看了我说的书应该不会这样写代码的
jishiping 2003-08-27
  • 打赏
  • 举报
回复
解决的办法,一是将begin()作为一个输出函数,由EXE在程序开始的时候执行。另外一个办
法,在DLL里创建一个计时器,在计时器里运行你的begin()函数,同时销毁计时器。比如:

UINT TimerID = 0;
VOID CALLBACK TimerFun(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
KillTimer(NULL, TimerID); begin();
}

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
switch(reason)
{
case DLL_PROCESS_ATTACH:
//DisbaleThreadLibraryCalls,见文后
TimerID = SetTimer(NULL, 0,
50, (FARPROC)TimerFun);
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return 1;
}
jishiping 2003-08-27
  • 打赏
  • 举报
回复
问题是这样的,首先Windows加载DLL时,首先执行DLL的DllEntryPoint函数(参数reason为
DLL_PROCESS_ATTACH)。DLL在执行这个函数时,可以作一些初使化的代码。但是,需要注意
DLL的这个函数,此时必须返回非0值,才表示DLL成功加载。

再来看看楼主的代码,在L的DllEntryPoint函数里,当reason为DLL_PROCESS_ATTACH时,他调用begin()函数,而这个begin()函数,执行一个循环,在循环里创建线程。由于此时DLL还
没有成功加载,所以此时创建的线程还不能够运行,直到DllEntryPoint返回非0值之后才运
行。由于DLL的DllEntryPoint函数,执行begin需要10个循环,每个循环需要10秒钟,共计需
要100秒,所以你的程序开始执行后,需要过100秒后,由begin()创建的10个线程才会运行,
而且基本上是同时运行。就是说过100秒后,10个MessageBox基本上同时出来。而并不是程序
结束后这些MessageBox才出来。

正确的写法,这个begin()不应该放在DllEntryPoint中执行。而是需要等到DLL成功加载后才
执行这个函数。
Behard 2003-08-26
  • 打赏
  • 举报
回复
我不认为这段代码在 EXE、DLL 中有什么不同
1. 《 Win32 多线程编程》上说得非常清除,看看这本书就知道了
2. 本来使用 CreateThread 来创建多线程,仅仅是从返回值判断是否创建成功
但是线程什么时候开始运行,并不是你能控制的
3. 你测试的不一样,可能是测试代码中是比较小的程序

-----------------------------------
现在混水园了!
appleing 2003-08-26
  • 打赏
  • 举报
回复
感想楼上的,我会去试试的,不过,以上只是一个测试代码,确实存在这种情况存在,我很想知道答案啊.
chenzhiguo 2003-08-26
  • 打赏
  • 举报
回复
我觉得问题不在于此.
DWORD WINAPI thread_code(LPVOID p)和void begin()
应该是导出型的.

我也是刚学,但是我看过很多DLL的写法了.正常情况下
都需要用导出类型的~

dll不和LIB一样.
appleing 2003-08-25
  • 打赏
  • 举报
回复
可能是DLL的运行机制和EXE的不同,导致的这样的结果.

有谁能给我指点一下吗?

这个是安全焦点一个前辈给我的回复,他只是说道了原理,我还是没有想到解决方法.郁闷

************************************
在加载DLL的时候,DLL开始执行begin();
而begin中要创建线程,这时候系统会再次以DLL_THREAD_ATTACH参数来调用DllMain,而由于DLL_PROCESS_ATTACH还没有返回,这时候这个DLL应该处于某种正在被加载状态,这时候CreateThread就会一直等下去,而这个等待是不可能完成的。
而当释放DLL的时候,系统必须卸载这个DLL了,这种Dll状态被改变,互锁就会被打破,可能是CreateThread发现DLL被卸载了,没有必要再等待下去了(也可能是系统通知CreateThread可以继续了),因此CreateThread终于被成功执行,线程也终于被创建。MessageBox也终于弹出了!
***********************************
appleing 2003-08-25
  • 打赏
  • 举报
回复
真的感想各位的帮助,我详细说明一下原因好了

这个问题是DLL里面的,

代码看起来是没有问题,因为我把代码放在exe中(也就是那个创建线程和线程函数),是没有问题的,10秒弹出一个box来,一起都是预料中的.

可是,一旦这些代码放在DLL中,主程序调用DLL的时候,按道理说应该和在exe中一样,10秒弹出一个box的,但是,实事并不是如此,box根本没有弹出来,DLL里面,代码只是不断的调用CreateThread函数,10秒调用CreateThread一次,但是没有弹出box!!

就在DLL调用结束,也就是释放DLL的时候,对话框终于弹出来了,并且由于某些原因(我不知道,估计是这个时候10个box一起弹出来),这个时候还出错了.

这段代码:

DWORD WINAPI thread_code(LPVOID p)
{
static int test = 0;
MessageBox ( NULL, "box", IntToStr(++test).c_str(), MB_OK );
//这个框框一直不弹出来,按理说应该是10秒一个才对
//为什么会等到这个dll释放了,才弹出来,并且出错了
}
//---------------------------------------------------------------------------
void begin()
{
for(int i=0;i<10;i++)
{
DWORD funid;
CreateThread(NULL, 0, thread_code, 0, 0, &funid);
Sleep ( 5000 );
}
}


放在exe和DLL中,同样是调用begin函数,居然产生不同的结果,很令我费解,我问了很多人,得到的只是口头原理上的解释,大体是这样的,我也说不明白:大概是dll会重复建立线程,然后线程又等待执行,产生死循环,在dll释放的时候,终于得到执行.

有个前辈告诉我DisbaleThreadLibraryCalls函数可以防止dll重复调用线程,可能对我的问题有帮助,但是,bcb里面,我无论加什么申明,lib,都无法调用这个函数,也非常的郁闷.

无奈之下,只好发贴求助.
Tiejun_Chenfang 2003-08-25
  • 打赏
  • 举报
回复
这个是上次的问题,我经过多方询问,大概知道了原因.
但是,问题仍然不得解啊,也许是我太笨了,

大概知道了什么原因,问题仍然不得解啊??????

pp616 2003-08-25
  • 打赏
  • 举报
回复
没看出问题。
Behard 2003-08-25
  • 打赏
  • 举报
回复
我试了没有什么问题呀
不过有可能是我没有理解你的意思
DWORD WINAPI thread_code(LPVOID p)
{
static int test = 0;
MessageBox ( NULL, "box", IntToStr(++test).c_str(), MB_OK );
//这个框框一直不弹出来,按理说应该是10秒一个才对
//为什么会等到这个dll释放了,才弹出来,并且出错了
}
//---------------------------------------------------------------------------
void begin()
{
for(int i=0;i<10;i++)
{
DWORD funid;
CreateThread(NULL, 0, thread_code, 0, 0, &funid);
Sleep ( 5000 );
}
}
yydy 2003-08-24
  • 打赏
  • 举报
回复
学习

1,221

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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