关于时钟的问题。我决定花300大元给大家送分,我因为我实在不想在网上找来找去了!!!(300分)

  • 主题发起人 aimingoo
  • 开始时间
A

aimingoo

Unregistered / Unconfirmed
GUEST, unregistred user!
是这样的,我有一个.DLL程序,在这个程序中,我需要用到一个全局的
时钟。当然,可以是一个Timer,也可以是用API创建的。
现在我尝试在.DLL的主程序.DPR中初始化一个Timer, 结果显然不容乐观,
TTimer.create的sender参数无法给一个有效的值,而且,onTimer事件也
无法给一个有效的事件函数。
因为如果用DLL进程中的值,DLL的线程是动态的!所以,这些值并不固定
,相对全局来说,是无意义的。
第二个思路是在DLL的线程中写一个TTimer。 天啊!每调一回DLL, 一个Timer产生!这还是全局的么?!一会儿系统就崩了!
================
没有思路了。 :(((
但是,我记得我在网上看到过一篇文章《如果在DLL中使用时种》,我的确
看到它了!但我当时没存下来,现在又找不着了!——我已经找了两天了
!wuwuw! 谁能告诉我,where is it?
或者,谁能帮助我,在DLL中创建一个全局的时种,而不是每个线程都要打
开一个!! ???!!! Help me!!
++++++++++++++++++++++
非常急!!!!
++++++++++++++++++++++
 
试试 WINAPI 函数
SetTimer(null,1,1,@yourhandle);

======================================
The SetTimer function creates a timer with the specified time-out value.
UINT SetTimer(
HWND hWnd, // handle of window for timer messages
UINT nIDEvent, // timer identifier
UINT uElapse, // time-out value
TIMERPROC lpTimerFunc // address of timer procedure
);

Parameters
hWnd
Identifies the window to be associated with the timer. This window must be owned by the calling thread. If this parameter is NULL, no window is associated with the timer and the nIDEvent parameter is ignored.
nIDEvent
Specifies a nonzero timer identifier. If the hWnd parameter is NULL, this parameter is ignored.
uElapse
Specifies the time-out value, in milliseconds.
lpTimerFunc
Points to the function to be notified when the time-out value elapses. For more information about the function, see TimerProc.
If lpTimerFunc is NULL, the system posts a WM_TIMER message to the application queue. The hwnd member of the message's MSG structure contains the value of the hWnd parameter.

Return Values
If the function succeeds, the return value is an integer identifying the new timer. An application can pass this value, or the string identifier, if it exists, to the KillTimer function to destroy the timer. If the function fails to create a timer, the return value is zero.
Remarks
An application can process WM_TIMER messages by including a WM_TIMER case statement in the window procedure or by specifying a TimerProc callback function when creating the timer. When you specify a TimerProc callback function, the DispatchMessage function simply calls the callback function instead of the window procedure. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.
The wParam parameter of the WM_TIMER message contains the value of the nIDEvent parameter.
See Also
DispatchMessage, KillTimer, MSG, TimerProc, WM_TIMER
 
Dll中全局的时钟, 什么意思? Dll中全局变量都无法设置又怎样设置全局时钟呢?
每个多线程中应该有自己的时钟. 全局的时钟只能放到主程序中.
 
第一,hui, DLL中可以有全局变量。
第二,wuyi, 用setTimer的方法试过了,在95/98上成,在NT上不成。
关于本问题,我已经解决了。分准备送给wuyi, 但我想先在这个贴子后
加个贴子,对本问题作一个详细解释,也给大家以后在这方面的编程提
供些路子,至少不会象我一样泡了四天网!
^-^
========
稍后分赃
 
我要看!
 
DLL和线程有什么必然关系呢?
DLL和Host App 可以是同一个线程啊!而且常常是!
至于全局的Timer,在哪里声明都可以,你可以用函数来传递它,或者
用SendMessage(...)发送到它该去的地方。
 
两边存东西进文件,通过文件交流怎么样.
我一般内存搞不定就这么做.
 
我很早写过,一年前吧。不过用的是SDK。
等您老分赃,咱也学学Delphi。
 
一定要用DLL吗?如果可以用Package,你去看看www.inprise.com.tw,李唯写的一篇《package的威力》(在推荐文章中),相信应该对你会有所帮助。
 
我也要看!
 
DLL中全局变量好搞,但全局Timer还真没见过!
我这就等您老分赃了
 
我也想学两招。
 
aimingo哪里去了?
我有解决办法的!
不听算了!
 
pegasus倒是说呀!
又在吊大家胃口了
坏坏的说!!
:<
 
不知你要全局TIMER干什么,如果不需要驱动事件的话,可以用全局变量代替:
建立一个全局变量,内容为当前时间,在需要取时间时再取一个当前时间,一
对比就可以得知经过多少时间了。问题是运行其中不能改系统时间,否则会出错。
另外线程中也可以定义线程变量,与上同。
是否太简单了?还是理解问题。建议把用途说出来才好。
 
DLL和主程序同步,再用全局变量的思路能行
 
我过去一直用c写DLL,分配全局变量绝对没有问题。难道Delphi的DLL中只支持线程局部存储变量?在c中,默认的变量是全局变量,申请线程局部存储变量才需要特殊处理。我一直认为无论用c还是Delphi写Dll应当是一样的。真的不行,就应当用c来写这个DLL,用函数SetTimer就行了。
 
讲讲你是如何实现的,思路和算法。
你的源程序是否可那来一读?或能否加入到我的Dll库中以供别人共享呢?
 
我的天,这段儿太忙,再加上我上大富翁老慢,所以就一直拖……
没有将这个贴子选进B计划,有些遗憾啊! 哈哈……
好的,现在给出这个贴子,请关注线程编程和动态链接库的定制
的朋友指正。
=================
=================
1. DLL工作原理
--------------
我只浅要地讲一下工作原理,以便于后面的叙述。
DLL是window为节约线程交互时间和提高代码共用性能而引入的。
它的特点在于一个DLL在系统中只被调入一次,当进程(如一个.exe)
操作申请一个.dll时,操作系统先查看系统内部是否已经调入该dll,
如果已经调入,操作系统便只在当前进程空间中制作一个.DLL公共变
量的拷贝,并且使用原进程空间中的DLL代码。
也就是说,任何时候,系统中只可以有一个.DLL的实例,但可以有任
意多个该DLL的数据拷贝。DLL的多个引用之间的代码是重叠的,而数
据是分开的。
2. 关于在进程间通讯,即DLL全局变量的问题。
--------------
好了,我们现在想到的事是,基于上述的原因,各进程间如果要涉及
数据交换就完了。因为各个DLL的各个实例通常运行在不同的地址空间
里。也就是说,一个.DLL文件通常被多个不同的.EXE调用,因此,数
据在各个.EXE独立的进程空间里。
1). 进程间共享数据的第一途径是DLL初始化。
DLL初始化中,可以给在interface中定义的全局变量赋初值。这个初
值在DLL的各个拷贝中都是相同的。至少,在申请到这个的最初,是一
样的。当然,必须记住的是,这只是在最初时相同的。
这句话在微软的标准文档中是这样解释的:“当加装了一个模块(EXE/DLL)
的两份拷贝,在可写数据还没有被修改时,在WinNT的进程共享数据”。
2). 进程间共享数据的第二途径是DLL全局内存块
说“全局内存块”,这种说法是不标准的。因为它的实际说法是“内存
映像文件”。这就好比我们打开了一个文件,A线程对文件的操作,对B
线程来说,是可见的。只不过,这个文件是打开在内存中的而已。
(一个内核的问题是,Window可能将这个映像文件建在磁盘上,但,这只
是操作系统的事,在程序设计这个级上,我们感觉它只是在内存中。)
这显然可以理解,任何对文件的操作都是实际的,你能够在不同的进程/
线程中同样的感知到同一个“内存映像文件”的修改。
3. 关于在线程间通讯,即线程全局变量的问题
--------------
线程间变量问题的解决是方便的,因为Delphi中可以象一个单元似的写
一个线程代码,你在单元接口声明的全局变量对所有线程来说,就是可
见的。除非你声明成了threadVar。
4. ISAPI-DLL的特殊性
--------------
很有意思的是,ISAPI-DLL通常只被一个.EXE调用。这是由IIS/PWS Server
的特殊性所决定的。因为IIS/PWS需要将ISAPI-DLL映射到自己的地址空
间,然后对由client(浏览器)端向这个DLL发出的http请求作出分配,并
交由ISAPI解释。所以,一个ISAPI-DLL通常只在一个.EXE中,有一个代码
实例,并且,在这个.EXE的代码空间中,可能同时拥有多个ISAPI线程。
所以,在ISAPI-DLL中所要处理的只是线程间通讯的问题,而不是进程间
的通讯问题。
5. 时钟问题的提出
--------------
这里的时钟问题的提出是偶然的,而且你可能只会在ISAPI-DLL的编写中
会遇见。下面讨论的方法也是目前能够使用的唯一可行方法。 :)
当时,我正在写一个聊天室系统,聊天室系统中要求对异常断线的用户
作出检测。这样,我需要在ISAPI中专门写一个线程来检测用户(浏览器)
端在较长时间没有发服务器发出一个登录请求。这个线程每1.5分钟发生
一次,每次扫描一遍全部用户列表,对登录记数器作出检测,当记数器小
于1时,就自动注销这个用户。
很显然,解决这个问题的最直接方法就是在ISAPI中实现一个时钟线程,
每1.5分钟触发一次就可以了。
前面的讨论已经讲过不能用Timer对象了。
Wuyi提到了用SetTimer(),这个方法的确有可行之处。我曾经用了这种方
法,很有趣,在95/98环境中可以,但在NT中就不行。——我没有在任何
资料中看到对setTimer()这个函数有使用限制的!——后来,我同公司的
另一个技术人员讨论时,想到了在IIS这一级上,可能对setTimer()作了限
制,的确很有可能,因为IIS(ISAPI-DLL)这一级是远端操作NT Server的,
微软的确可能在这一级上对SetTimer()作出限制。
由于ISPAI-Filter(过滤器)中服务器级别的,我相信在Filter中可以使用
setTimer(),但在ISAPI-DLL(CGI)上的确没有办法使用。 :(
6. 时钟问题的解决
--------------
想了四天,很简单。但得换个思路。^-^
——请创建一个线程,在这个线程的Execute()中,做一个死循环(放心,
我的确需要这样一个只有.dll死掉才停止的进程),在循环中用一个sleep()函
数虚拟一个时间的延时就成了。
哈哈,很简单吧。的确很简单。 :)
上面的问题全解决了:
1) 由于新线程与.dll的所有线程位于同一地址空间(同一.EXE)内,所以可以
安全地访问任何全局变量。不用考虑进程间交互的问题。
2) sleep()是一个安全的延时函数,它使当前线程停止对CPU时钟的使用,直
到延时结束。所以不需要考虑该线程因为sleep()导致效率或者阻塞问题。
7. 关于大家答案中的一些问题
--------------
to huizhang :“Dll中全局变量都无法设置又怎样设置全局时钟呢?”
DLL中可以有全局变量,上面的讨论中提到了两种实现全局变量的方法:初始
化变量和内存映象文件。
to wsh :“DLL和Host App 可以是同一个线程啊!而且常常是!”
Host App是指一个宿主的应用程序,应用程序会被初始化成一个进程。并且,
每一个进程会拥有一个主线程。一个Host App对一个.dll的引用是将.dll载入
了应用程序的进程空间,并创建了一个处理线程。这意味着DLL和Host App并
不是同一个线程,只是在第一次调用时会和Host App处于同一地址空间而已。
而且,通常DLL与Host App并不处于同一个地址空间,新的应用程序调用只会
得到一个DLL的共享数据拷贝而已,代码已经不在同一地址空间了。
to duz:“真的不行,就应当用c来写这个DLL,用函数SetTimer就行了”
在ISAPI-DLL这一级上,Delphi与C的处理是差不多的。Delphi没有为ISAPI写
太多的东西。 :( 上面讨论的技术在C和Delphi中是一致的。——我想,在C写
的ISAPI中,也可能无法使用setTimer(),我想可能是microSoft IIS的限制。
to pegasus:
什么好招???哈哈……
我暂时不关闭本问题吧。放在这儿大家看看,有什么不对的地方,请指正啊!
分是Wuyi的啊,如果大家还有什么新思路,还可以再抢抢…… ^0^
 
接受答案了.
 
顶部