我现有一个程序C/S架构的,其主要功能是记录用户进行每一个功能窗口的进行时间,和退出时间。如用在MDI程序中,用户进入子窗体1时,我要记录进入时间,退出子窗体1时,我要记录退出时间。用户进入子窗体2时,我要记录进入时间,退出子窗体2时,我要记录退出时间。当然用户可以同时打开多个子窗体。还有用户数是不定的,有多少个用户就有多少个客户端    现在的问题是,如果用户正常退出,只需要在closing中添加退出方法就可以了,但用户非正常退出,如结束进程,程序非法,停电等。我怎么记录用户的退出时间呢。    我想的方法是在数据库时新建一退出张表,当用户时入系统时,生成一个用户唯一ID号,当某一个用户进入某一个窗体是,就我就生成进入窗体唯一ID号,除了向日志表里写入进入模块时间,还向退出表添加一条用户唯一ID号、窗体唯一ID和当前时间的记录。当我每做一个操作时都修改这些记录的时间,如果退出窗体时我就删除对应窗体唯一ID的记录,而数据库用作业进行每隔30分钟的检查任务。检查出当前系统时间和进记录中的时间之差大于30,我就认为该用户非法退出,查出窗体唯一ID,修改日志表中相应的退出时间。在删除这些记录,当然用户每次操作是都要检查这些记录是否存在,如果不存在则代表超时。但这样做的话,会多次向数据库进行通讯,几乎每个操作都要检查记录,修改时间,完成正常操作这三次通讯,不仅要多写很多代码,而在用户数或打开窗体过多的时,退出表的记录数会很大,对数据库的压力也大。
    
    现在除了websevice可以利用以外,由于特殊要求,无法在程序和数据之间加一层以主动检查用户是否退出。只能在程序 webservice和数据库上想办法。我想程序在停电,系统重启这种情况下就根本没有办法检查的。

解决方案 »

  1.   

    利用Session 。 轮询不可取。
    用户登录时在服务端记录session。跟asp.net的一样。 session_timeout时记录退出时间就行了。
      

  2.   


    我没有办法在中间加一层,只有客户端程序,数据库,不能有其他的东西还想问一下这个“心跳包” System.Threading.Timer t = new System.Threading.Timer            (new System.Threading.TimerCallback(watchTheLoginUser), o, 1000, 1000);            
    这段代码能用在B/S上吗
      

  3.   

    如果只有客户端和数据库,可以把轮询的工作放到数据库里来执行,以SQL Server为例,建一张在线用户表,里面存放每一个客户端的最后一次心跳的时间,再写一个存储过程,从在线表里找出牺牲了的用户,而在客户端只要去更新这个表里的内容就可以了,别告诉我你连客户端的程序都没有办法改啊。
    存储过程有了以后,在SQL Server里添加一个计划执行的任务,这个任务很简单,就是调用那个存储过程,间隔时间嘛你就看着办吧。如果不会设置,或者你所用的数据库不支持这个功能,也可以写一个简单的程序运行在数据库服务器上,然后定时执行那个存储过程,或者干脆用Windows的计划任务功能。