困惑了,哪些组件是线程安全的呀?

第1个问题RT,下面是个测试的代码
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#include "Unit1.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------

// Important: Methods and properties of objects in VCL can only be
// used in a method called using Synchronize, for example:
//
// Synchronize(UpdateCaption);
//
// where UpdateCaption could look like:
//
// void __fastcall TTest::UpdateCaption()
// {
// Form1->Caption = "Updated in a thread";
// }
//---------------------------------------------------------------------------

__fastcall TTest::TTest(bool CreateSuspended)
: TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void __fastcall TTest::Execute()
{
//---- Place thread code here ----
int Count=0;
while(!Terminated)
{
Count++;
Form1->Caption = "Updated in a thread" + IntToStr(Count);
Form1->Button1->Caption = IntToStr(Count);
}
}
//---------------------------------------------------------------------------
如果这样写代码,并且只有一个线程在运行,我感觉是不会有问题的.
实际上,我们很多线程都是这个作用,无非是让界面可以响应用户的操作并反映过程中的变化,
所以,我觉得这么写应该没有问题,不知道大家的意见怎么样?
[1478 byte] By [jaffy-小胖猫_笨猫先飞] at [2008-4-24]
# 1
怪了,人都跑哪去了,怎么没有人回答呢?
# 2
不是没有问题,而是很有问题!只要是其他线程想要操作主线程界面有关的,如果不做 Synchronize,即是你只有一个子线程,也不行,只是这个时候你大多数时候看起来好像是正常的,当出问题时你就哭得来不及了。:(^-^
# 3
如果我只有一个线程实例呢?并且主线程没有操作这些控件就不会发生冲突呀.
我主要感觉这样写代码很直接,并且有的时候带参数情况下的过程,不好在线程中序列化.
第1个问题谁来解答啊?
# 4
vcl,可视化控件应该都不是线程安全的。有些不可视化控件是线程安全的,不过,要我列个表说出来,我也不知。呵~。
如果我只有一个线程实例呢?并且主线程没有操作这些控件就不会发生冲突呀.我觉得你这样说很牵强。因为谁都不知道他会什么时候以何种方式发生冲突(因为代码写程那样已经决定了那个潜在可能)。我觉得写代码不是说我认为可以做到什么而可以怎么样,而是,考虑当有这些问题时,我该怎么避免或修复, 至有线程中序列化,那就考各人技巧了。
# 5
to : netliuming
谢谢你的意见,其实我以前都是用消息来传递的,后来偶然直接用主线程的变量或者直接操作界面,感觉很方便,所以就偷懒了.
带参数的序列化不知你有什么好方法,特别是线程中需要变更主线程上很多的控件和变量的时候?
另外,想听听更多人的意见.
# 6
带参数的序列化不知你有什么好方法,特别是线程中需要变更主线程上很多的控件和变量的时候。
这个问题,估计所有用bcb,delphi的都很想知道的,我也是。不知道vc是否也有这个困惑。
我现在是通过参照修改Synchronize的源代码来实现
typedef void __fastcall ( __closure * TSafyMethod )( void * );
void ExecInMainThread( TSafyMethod SafyMethod , void * Context, bool Queued = false );
这样在线程中可以直接这样调用ExecInMainThread(SafyMethod, //函数方法,
Context //参数
);
但也不是很方便,需要专门做一个类参数来进行传递。
# 7
我昨天下班做了个测试,将一个串口读写软件挂着,挂了15个小时,还没出问题.
这个软件有些部分的控件控制,我就是直接操作的主线程的变量和控件,并且一个MEMO不停的记录线程中的变化.MEMO也是直接写的,感觉早上来的时候没出问题.日志还照常记录,大概有81万行记录.我相信继续记录应该也没问题.
所以,我想不通为什么非要写在Synchronize中?
# 8
很乐于探讨,我也讲一下自己的亲身经历,我以前有个显示传输的界面,显示速率,进度什么的。当时由于用了事件机制,子线程里又再调用另一个处理函数再触发外部事件, 这样就忘了加Synchronize. 就这样跑了相当一段时间感觉一点问题也没有,测试部测试也未能发现问题,可能出了问题不注意也不知道是问题. 很久后,才有人发现有时候显示的速率等数据不太符合实际。一开始以为那里计算错了,查了很久,改了很多东西,也还是会时不时出现,直到叫同事帮我看代码会诊才找出来,搞得灰头土脸,因为自己已经先入为主,我是不会不调用Synchronize的,从没往这方面想。
# 9
基本上没特别说明的都是不安全的
LuoGD-抢第一楼 at 2007-10-22 > top of Msdn China Tech,C++ Builder,基础类...
# 10
包括一个简单的int a这个变量
LuoGD-抢第一楼 at 2007-10-22 > top of Msdn China Tech,C++ Builder,基础类...
# 11
我现在发现,如果只有一个线程实例,在线程中引用主线程的变量和对主线程进行赋值,不会有问题.因为,实际上这个时候,线程的作用和定时器差不多了,没有其他的事件会与它发生冲突.当然,如果有多个实例则肯定会出问题.
# 12
对于Caption属性,很多控件写Caption的时候只是一个SendMessage(看VCL代码),在线程里直接写Caption也不会有大问题,因为消息队列相当于把这个问题序列化了.

不过我想如果Caption里的写操作的时候除了SendMessage后面还加了一些如FCaption=Data之类的代码,那就绝对不线程安全了
Waiting4you-毛毛 at 2007-10-22 > top of Msdn China Tech,C++ Builder,基础类...
# 13
希望更多人发表意见,希望听到各种不同的声音.
# 14
mark
MultiThread_begin-pp at 2007-10-22 > top of Msdn China Tech,C++ Builder,基础类...