俺没玩过多线程,高手指点需要注意的地方?
我正在做关于多线程下载方面的东东,以前没有做过多线程,所以没有经验,请高手指点一下
我用了个AdvStringGrid用于指示当前下载的文件相关信息.
包括文件名,大小,和本地文件对比是否需要更新,下载速度,以及哪个线程在下载这个文件.
在线程中,首先查找没有下载的文件,我用了一个可变数组,其基类型是指向记录类型的指针
找到后开始下载,在下载过程中显示进步.
有以下几个方面感到迷域.
比如说, 在主程序中,有一停止按钮,用来停止所有线程.
具体办法是将一个全局逻辑型变量abortthread设为真时停止线程.
我在线程里用Synchronize(取abortthread值到一个临时变量里),再检查这个临时变量的值
这样做发现很影响下载速度.后来通过看书,在主程序中用threadvar来说明abortthread的类型.
我的问题是:这个全局变量的存取是否必须在Synchroniz()中,或其他同步或临界区等方法中.
能不能直接对这个全局变量的存取.
高手能否总结哪些是线程安全的? 即在线程中能直接存取.
关于threadvar,这个具体用在什么时候,用这个说明变量,是否就可以直接存取了.
多个线程下载时,需要显示下载速度.这时需要对AdvStringGrid中的CELL进行操作.这时也必须在
Synchroniz()中,或进入临界区等方法.
这样的操作,也会影响线程的执行速度!
我后来改用了自定义消息,但传到主线程中处理时,我给MSG的两个参数,赋给的是一个指针.
postmessage后,想主线程处理这个消息时,这个指针所指向的内容已发生变化,结果在消息处理中显示下载状态是,是错误的.
看到书中指出来的 sendmessage须等待消息处理完,再执行后面的.
所以不想用这个,主要想提高一下速度.
再在网上查,看到用内存映射文件,完成进程之间的通讯.但没有深看
高手们,有指点一下,你们是如何处理多线程这些地方的.
不用同步,出现一些内存共享冲突,头都大了,但全用同步,发现速度降了很多.
说的有点乱,望谅解.我困在这里很久了.
本贴我还会修改的,现在仓促一些,有空再修改一下.!
问题点数:100、回复次数:22Top
1 楼aiirii(ari-http://spaces.msn.com/members/aiirii/)回复于 2006-04-05 23:28:48 得分 5
>>我的问题是:这个全局变量的存取是否必须在Synchroniz()中,或其他同步或临界区等方法中.
能不能直接对这个全局变量的存取.
用 同步信号,或 临界区 是更好的解决方法
不要用 全局变量
>>关于threadvar
>>看到书中指出来的 sendmessage须等待消息处理完,再执行后面的.
PostThreadMEessageTop
2 楼ZyxIp(绝望中...)回复于 2006-04-06 00:58:55 得分 10
<WINDOWS核心编程>一书仔细看看.
将所有的线程保存到一个列表中,停止时分别调用每个线程的STOP方法.
多个线程之间应尽量少的交互.
和主窗体界面的交互用POSTMESSAGE消息的方式.
最重要的是要将你的工作逻辑分清楚,主要要从设计上避免性能的下降.Top
3 楼clasj(★知我☆)回复于 2006-04-06 11:03:49 得分 0
学习Top
4 楼happyct(绿叶对大树的情怀)回复于 2006-04-06 11:42:22 得分 5
其实,下载程序的速度瓶颈是在数据的存储。(网络没有限速的情况下)
用共享内存是可以解决问题,如果不是很熟悉的话,那么你可以考虑分段下载,分段存储,都下载完后,再合并Top
5 楼maxtool(≮From NingBoo≯)回复于 2006-04-06 14:22:37 得分 0
进来学习~~~Top
6 楼solokey(争取在2008年成为低级程序员)回复于 2006-04-06 21:47:32 得分 20
windows核心编程+win32多线程程序设计
都看一看..这2本书都是有电子版的.Top
7 楼lindamis(林子)回复于 2006-04-06 23:07:51 得分 0
感谢楼上的,该需要恶补的时候了,我在网上找到了这两本书windows核心编程+win32多线程程序设计
好好学习一下~~~~~~~~Top
8 楼coreblood(I don't Know )回复于 2006-04-06 23:10:43 得分 0
学习Top
9 楼linzhengqun(风。我回来了)回复于 2006-04-07 09:14:13 得分 20
也可参考这里面的线程杂谈:
blog.csdn.net/linzhengqunTop
10 楼lindamis(林子)回复于 2006-04-07 18:57:41 得分 0
感谢楼上的,linzhengqun(风。我回来了) ,我已经保存了相关网页Top
11 楼YaYiYaO()回复于 2006-04-08 10:27:36 得分 40
1、线程的同步最好不要用Synchronize,很影响数据(Synchronize的真实面目是用主线程去执行相关的内容,这样还影响对用户操作的响应),最好用“互斥体”或“临界区”(EnterCriticalSection)。
2、结束线程不需要设全局变量,在线程类中设一个成员变量(比如:Fstoped:boolean),要停止的时候,主线程中用个循环将每个线程中的Fstoped置为真就好了
3、显示速度不需要同步(多线程中少用点同步,不然多线程的优势就体现不出来了),可以用窗体消息,速度改变时,线程向主窗体发个消息,窗体收到消息,改变AdvStringGrid中的内容
这些只是我的一些看法,不一定都对,大家相互学习学习,呵呵!!Top
12 楼YaYiYaO()回复于 2006-04-08 10:32:54 得分 0
不好意思,没看到下面你说的用postmessage
如果考虑速度用postmessage好,sendmessage要等待响应
postmessage不需要发指针地址,把线程和AdvStringGrid的行对应起来,发消息的时候只要发哪一行,什么速度就好了,这样肯定不会冲突Top
13 楼lindamis(林子)回复于 2006-04-09 17:25:44 得分 0
感谢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这个控件发消息吗?
麻烦你真体说一下,我对消息和线程都是头一回使用。Top
14 楼YaYiYaO()回复于 2006-04-10 08:38:40 得分 0
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:处理自定义消息的方法有很多,我这里说的只是其中一种。如果觉得我这里说的不大清楚,你可以去找些例子看一下,应该还蛮简单的Top
15 楼shuihan20e(站的更高,尿的更远)回复于 2006-04-10 11:58:07 得分 0
我也来学习Top
16 楼lindamis(林子)回复于 2006-04-12 00:25:58 得分 0
YaYiYaO大师的指点,让我有点拔云见山,呵呵!!!
我改用发送消息,下载速度提高很多.(只差查找文件,还没改!),高兴~~~~~~~~~~
我用记录类型存放下载的文件相关数据,如,在grid中的行号,线程号,下载的速度等等...
在用 NEW(指向文件录的指针)申请地址后,将指针所指向的记录赋以文件相关数据
然后将这个指针作为POSTMESSAGE的参数,
在窗口程序的消息处理中,根据指针取出记录,更新ADVSTRINGGRID
再用DISPOSE释放指针所指向的内存
这样的做法是否正确?如果不释放,会不会造成内存泄漏?Top
17 楼YaYiYaO()回复于 2006-04-12 12:46:46 得分 0
理论上没什么问题,应该可行。自己多多调试吧,呵呵
ps:偶不是大师啦,第一次有人叫偶大师,hoho!!~~~
只是也做过些多线程方面的东东,对windows消息有那么一点点了解而已,大家相互学习学习Top
18 楼lindamis(林子)回复于 2006-04-16 22:28:49 得分 0
现在遇到的问题是发送的消息有可能丢失,我通过application.onmessage实现的.
如何确保发送的消息,百分百被处理?
另外我在主线程中,循环等待其他线程结束,在循环中,既要检测线程是否结束,并且还要处理线程发送的消息,为了降低CPU占用率,用msgwaitformultiobject是否合适.
请告诉其正确用法.或有什么其他更好的办法,使主线程所使用的CPU占用率最低Top
19 楼lindamis(林子)回复于 2006-04-17 23:24:33 得分 0
自己顶~~~~~~Top
20 楼lindamis(林子)回复于 2006-04-18 23:13:42 得分 0
自己顶~~~~~~
Top
21 楼YaYiYaO()回复于 2006-04-20 08:46:23 得分 0
要百分之百被处理的话就用sendmessage吧,但是这样影响速度,自己选择
但是我觉得这里消息只是通知主线程更改显示的内容,偶尔有几条数据收不到,应该没什么关系吧
至于“msgwaitformultiobject”,sorry,没用过Top
22 楼lmxlj(疯狂)回复于 2006-04-21 06:36:45 得分 0
为什么一定要用主线程呢,为什么不再另外启用一个线程呢,因为主线程有很多工作要做,所以不适合你说的对GRID进行操作.当然影响.Top




