我正在做关于多线程下载方面的东东,以前没有做过多线程,所以没有经验,请高手指点一下我用了个AdvStringGrid用于指示当前下载的文件相关信息.
包括文件名,大小,和本地文件对比是否需要更新,下载速度,以及哪个线程在下载这个文件.在线程中,首先查找没有下载的文件,我用了一个可变数组,其基类型是指向记录类型的指针
找到后开始下载,在下载过程中显示进步.有以下几个方面感到迷域.比如说, 在主程序中,有一停止按钮,用来停止所有线程.
具体办法是将一个全局逻辑型变量abortthread设为真时停止线程.
我在线程里用Synchronize(取abortthread值到一个临时变量里),再检查这个临时变量的值
这样做发现很影响下载速度.后来通过看书,在主程序中用threadvar来说明abortthread的类型.我的问题是:这个全局变量的存取是否必须在Synchroniz()中,或其他同步或临界区等方法中.
能不能直接对这个全局变量的存取.高手能否总结哪些是线程安全的? 即在线程中能直接存取. 
关于threadvar,这个具体用在什么时候,用这个说明变量,是否就可以直接存取了.
多个线程下载时,需要显示下载速度.这时需要对AdvStringGrid中的CELL进行操作.这时也必须在
Synchroniz()中,或进入临界区等方法.
这样的操作,也会影响线程的执行速度!我后来改用了自定义消息,但传到主线程中处理时,我给MSG的两个参数,赋给的是一个指针.
postmessage后,想主线程处理这个消息时,这个指针所指向的内容已发生变化,结果在消息处理中显示下载状态是,是错误的.看到书中指出来的 sendmessage须等待消息处理完,再执行后面的.
所以不想用这个,主要想提高一下速度. 再在网上查,看到用内存映射文件,完成进程之间的通讯.但没有深看高手们,有指点一下,你们是如何处理多线程这些地方的.不用同步,出现一些内存共享冲突,头都大了,但全用同步,发现速度降了很多.
说的有点乱,望谅解.我困在这里很久了.本贴我还会修改的,现在仓促一些,有空再修改一下.!

解决方案 »

  1.   

    >>我的问题是:这个全局变量的存取是否必须在Synchroniz()中,或其他同步或临界区等方法中.
    能不能直接对这个全局变量的存取.用 同步信号,或 临界区 是更好的解决方法
    不要用 全局变量>>关于threadvar>>看到书中指出来的 sendmessage须等待消息处理完,再执行后面的.
    PostThreadMEessage
      

  2.   

    <WINDOWS核心编程>一书仔细看看.将所有的线程保存到一个列表中,停止时分别调用每个线程的STOP方法.多个线程之间应尽量少的交互.和主窗体界面的交互用POSTMESSAGE消息的方式.最重要的是要将你的工作逻辑分清楚,主要要从设计上避免性能的下降.
      

  3.   

    windows核心编程+win32多线程程序设计
    都看一看..这2本书都是有电子版的.
      

  4.   

    感谢楼上的,该需要恶补的时候了,我在网上找到了这两本书windows核心编程+win32多线程程序设计
    好好学习一下~~~~~~~~
      

  5.   

    也可参考这里面的线程杂谈:
    blog.csdn.net/linzhengqun
      

  6.   

    感谢楼上的,linzhengqun(风。我回来了) ,我已经保存了相关网页
      

  7.   

    1、线程的同步最好不要用Synchronize,很影响数据(Synchronize的真实面目是用主线程去执行相关的内容,这样还影响对用户操作的响应),最好用“互斥体”或“临界区”(EnterCriticalSection)。
    2、结束线程不需要设全局变量,在线程类中设一个成员变量(比如:Fstoped:boolean),要停止的时候,主线程中用个循环将每个线程中的Fstoped置为真就好了
    3、显示速度不需要同步(多线程中少用点同步,不然多线程的优势就体现不出来了),可以用窗体消息,速度改变时,线程向主窗体发个消息,窗体收到消息,改变AdvStringGrid中的内容这些只是我的一些看法,不一定都对,大家相互学习学习,呵呵!!
      

  8.   

    不好意思,没看到下面你说的用postmessage
    如果考虑速度用postmessage好,sendmessage要等待响应
    postmessage不需要发指针地址,把线程和AdvStringGrid的行对应起来,发消息的时候只要发哪一行,什么速度就好了,这样肯定不会冲突
      

  9.   

    感谢YaYiYaO()!
    针对你说的那几条,我把我的情况说一下
    1、我原先是用TCriticalSection,在主程序中声明的。在线程中:进入临界区 my_CriticalSection.enter
    查找没有下载的文件
    退出临界区 my_CriticalSection.leave找到文件后
    进入临界区 my_CriticalSection.enter
    更新ADVSTRING ,显示下载开始及线程编号
    退出临界区 my_CriticalSection.leave用FTP控件进行下载,在进度的事件中
    进入临界区 my_CriticalSection.enter
    更新ADVSTRING ,显示当前下载速度
    退出临界区 my_CriticalSection.leave在下载结束后
    进入临界区 my_CriticalSection.enter
    更新ADVSTRING ,显示下载完成
    退出临界区 my_CriticalSection.leave这样的架构中,发现有时某个线程,停止不动了,是不是死锁了。
    后来改用Synchronize就没有出现过这样的问题。是不是我有些地方没组织好2、主线程可以直接对子线程中的变量直接读写,这点我确实不知道,我试试3、关于postmessage,你说的是直接给AdvStringGrid这个控件发消息吗?
       麻烦你真体说一下,我对消息和线程都是头一回使用。
      

  10.   

    1、如果使用消息更新AdvStringGrid,就不需要用到这么多的同步了,因为消息是采用队列形式的,至于为什么回停止,这里也看不出来
    2、线程你应该是从TThread继承过来的一个类吧,你把变量放public中,主线程就可以随便访问了
    3、你可以先自定义一个消息(如:MM_UPDATEGRID = WM_USER + 110,WM_USER后为windows保留的用户自定义消息),消息只要发给放AdvStringGrid的窗体就ok了,然后在主窗体的类中定义一个函数用来处理这个消息(如:procedure UpdateGrid(var Message:TMessage);message MM_UPDATEGRID;这里过程名称随便,参数名称也无所谓,但一定要加var,类型为tmessage,然后后面加message MM_UPDATEGRID,MM_UPDATEGRID就是前面自定义的消息)ps:处理自定义消息的方法有很多,我这里说的只是其中一种。如果觉得我这里说的不大清楚,你可以去找些例子看一下,应该还蛮简单的
      

  11.   

    YaYiYaO大师的指点,让我有点拔云见山,呵呵!!!我改用发送消息,下载速度提高很多.(只差查找文件,还没改!),高兴~~~~~~~~~~我用记录类型存放下载的文件相关数据,如,在grid中的行号,线程号,下载的速度等等...在用 NEW(指向文件录的指针)申请地址后,将指针所指向的记录赋以文件相关数据
    然后将这个指针作为POSTMESSAGE的参数,在窗口程序的消息处理中,根据指针取出记录,更新ADVSTRINGGRID再用DISPOSE释放指针所指向的内存这样的做法是否正确?如果不释放,会不会造成内存泄漏?
      

  12.   

    理论上没什么问题,应该可行。自己多多调试吧,呵呵ps:偶不是大师啦,第一次有人叫偶大师,hoho!!~~~
    只是也做过些多线程方面的东东,对windows消息有那么一点点了解而已,大家相互学习学习
      

  13.   

    现在遇到的问题是发送的消息有可能丢失,我通过application.onmessage实现的.
    如何确保发送的消息,百分百被处理?另外我在主线程中,循环等待其他线程结束,在循环中,既要检测线程是否结束,并且还要处理线程发送的消息,为了降低CPU占用率,用msgwaitformultiobject是否合适.
    请告诉其正确用法.或有什么其他更好的办法,使主线程所使用的CPU占用率最低
      

  14.   

    要百分之百被处理的话就用sendmessage吧,但是这样影响速度,自己选择
    但是我觉得这里消息只是通知主线程更改显示的内容,偶尔有几条数据收不到,应该没什么关系吧
    至于“msgwaitformultiobject”,sorry,没用过
      

  15.   

    为什么一定要用主线程呢,为什么不再另外启用一个线程呢,因为主线程有很多工作要做,所以不适合你说的对GRID进行操作.当然影响.