C++Builder 程序员博客
19 Aug
另外请问通过主界面的ado访问数据库算不算vcl操作?
ADO组件也是VCL的一部分. 当然算是VCL操作.
看来这个问题是没人会了
楼主研究下临界区
使用同步和互斥访问vcl资源即可保证线程安全操作。
如果要用VCL最好用tthread来派生一个线程,如果用API生成的线程,有时会挂死。(呵呵,不知道是不是我水平臭)
19 Aug
我创建了两个线程
thread1和thread2
thread1的Execute()函数里代码是Synchronize(BitBtn1->Click());
thread2的Execute() 函数里代码是Synchronize(BitBtn2->Click());
我在主窗口里写上
thread1 *newthread1 = new thread1(false);
thread2 *newthread2 = new thread2(false);
好像BitBtn1->Click()和BitBtn2->Click()不是同时触发的
我以前以为是BitBtn->Click()和BitBtn2->Click()里有公共的VCL控件和资源导致
thread1和thread2结束后使用的时间很长(我用多线程就是为了把事情分开做然后结束后合并以节省时间)
可我把公共的东西全部去了还是一样
我怀疑BitBtn2->Click()是在BitBtn1->Click()结束后才触发的
我找了多线程的源码的 BCB自带的例子也看得不怎么懂 貌似是同一件事情并发出多次
而我要的是不同事情同时触发
请高手解惑
补充:我CPU是单核的 跟CPU有没有关系
那我该怎么办?
线程里不用VCL 不用Synchronize 能不能实现
线程里面执行的是什么东西?是计算,还是什么?
线程里是从硬件里读数据 计算 线程1大概就是测量一个LED的电压 电流 亮度 极性 漏电 什么的
线程2就测量 那个LED灯的颜色 读出来的数据显示到窗口上
我把VCL控件全部去除 在线程外把数据传送到VCL控件里
有没有并行操作的例子?我这里有几本书都是写的一个线程并行的
网上的例子也没找到我能用的
实在是没办法
要怎样才能让两个线程并发执行?
绝对并行不太现实,也没太大意义,不妨设法协调好,让需要同时做的事尽量安排在一起,使其看上去是“同步”的,如果有些工作不一定非要同时做,还不如用异步的,效率还高
楼主的需求应该不复杂的,可以考虑线程给主窗体发送消息。
线程计算出结果,然后把结果通过消息发送给主窗体,主窗体只负责显示,不参与计算,这样用户的体验更好点
至于如何发送消息等,可以搜索论坛
SendMessage是发消息并等待消息的处理结果,然后再执行一下句,线程在等待的时候,是不工作的
PostMessage是把消息放到消息队列里就返回继续执行下一句。
楼上说的对,还有个办法是用公共变量,复杂点的可以用容器,线程不断把要显示的东西往里填充,窗体不断从里面提取并显示,访问时用临界区锁死,这样工作线程和窗体的耦合度也能降低
你希望是同时触发还是分开触发呢?
你的代码明显是两个不同的线程,相互没有影响,也没有关系。
<
<
如果对VCL操作非常频繁,或者要求非常即时,在机器性能满足的情况下按部就班的用同步也没什么不对,如果性能跟不上,就得考虑一下设计思路,是不是某些显示要折衷一下,比如批量显示以减少冲突的机会,或者干脆减少显示(因为某些可能不是必要的),这个只能具体情况具体分析
vector可以,也可以用deque作队列,一头进一头出更清晰一些
同时也可以用串行来逼近嘛,到底要有多同时?
就显示个界面,为什么一定要同时触发呢? 这是不可能的
<
问题已经解决了 谢谢CppFile提示用了Synchronize就不是一起执行的
谢谢hind24耐心回答 虽然没按你的提示解决 但也让我学到了知识
17 Aug
另外请问通过主界面的ado访问数据库算不算vcl操作?
ADO组件也是VCL的一部分. 当然算是VCL操作.
看来这个问题是没人会了
楼主研究下临界区
使用同步和互斥访问vcl资源即可保证线程安全操作。
如果要用VCL最好用tthread来派生一个线程,如果用API生成的线程,有时会挂死。(呵呵,不知道是不是我水平臭)
2 Aug
请问线程怎么延时发送消息给自己??
用 Sleep(10)试试?
Sleep(2000);
PostThradMessage(自己的线程ID, 线程消息, WParam, LParam);
用Sleep不行啊,当自己阻塞了,不能处理其他事件了。
线程是基于事件处理的:
void __fastcall TSubThread::Execute()
{
MSG msg;
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
while(GetMessage(&msg,NULL,0,0))
{
this->Dispatch(&msg.message);
}
}
有没有办法在消息处理的时候,给自己线程发一个延时消息,延时时间到,消息自动触发。
不用谈实现了,你还是讲讲你的需求吧。
需求就是写个gprs服务端端DLL,
TCPIP协议传输字节流,在字节流基础上有自定义包格式。
DLL能把gprs客户端传输的数据包要能解析出来,传给应用程序,
应用程序发送命令,通过DLL再传给gprs客户端。
我建了一个线程,然后再线程里面建了一个隐藏窗口,
隐藏窗口处理SOCKET事件,其他事件则在线程中处理。
我要周期地查询SOCKET队列,把SOCKET队列里的数据包解析出来,并回复应答。
窗口事件是在线程事件里面调度的,如果线程被阻塞,窗口事件也会被阻塞。
23 Jul
线程里调用dll,dll相应的头文件有消息的定义: #define WM_DIAL_MSG WM_USER+101
我在线程头文件里定义了:
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_DIAL_MSG,TMessage,UpdateCaption8_mes);
END_MESSAGE_MAP(TThread);
报错如下:
[C++ Error] Registry.hpp(71): E2040 Declaration terminated incorrectly
为什么会有这个我看不懂的错?是不是END_MESSAGE_MAP(TThread)有问题?求高手解决,谢谢
看起来没有明显的错误.
你可曾修改过头文件registry.hpp?
没有修改
struct TRegKeyInfo
{
int NumSubKeys;
int MaxSubKeyLen;
int NumValues;
int MaxValueLen;
int MaxDataLen; //这行出错
_FILETIME FileTime;
} ;
有谁能帮我解决啊?
那就是你的工程代码中有某处代码有问题了.尝试将部分代码注释,然后编译,看是否还提示.
线程类里不能直接使用消息映射,楼主可以生成一个隐藏窗口,在隐藏窗口的窗口过程里处理消息。
头文件:
#ifndef Unit1H
#define Unit1H
//—————————————————————————
#include <Classes.hpp>
//—————————————————————————
class TMyThread : public TThread
{
private:
HWND m_hwnd;
//隐藏窗口过程
void __fastcall HidenWndProc(TMessage &Msg);
protected:
void __fastcall Execute();
public:
__fastcall TMyThread(bool CreateSuspended);
};
//—————————————————————————
#endif
//cpp文件:
__fastcall TMyThread::TMyThread(bool CreateSuspended)
: TThread(CreateSuspended)
{
//设置隐藏窗口即过程
m_hwnd = AllocateHWnd( HidenWndProc );
}
//—————————————————————————
//隐藏窗口过程
void __fastcall TMyThread::HidenWndProc(TMessage &Msg)
{
}
//—————————————————————————
void __fastcall TMyThread::Execute()
{
//—- Place thread code here —-
}
//—————————————————————————
mark。。学习!~~
支持fxworld
VCL_MESSAGE_HANDLER(WM_DIAL_MSG,TMessage,UpdateCaption8_mes);多了一个分号吧!印象中好像定义这些事不用写分号的。
学习一下
应该是ThinkHand说的那样,头文件定义的消息映射中不能有分号
<
自己构造消息泵
回复ThinkHand:
应该要分号,帮助文档里就有分号。
楼主用的那个版本的啊!我在6和2010下定义的都不用“;”的,说明书是什么地方带的,我学习一下。
fdsffewfwefqfwef
11 Jul
本人程序基本结构是这样:
主线程(应用程序)+子线程;主线程使用一个Sqlite实例,每启动一个子线程后子线程都会自己单独创建一个Sqlite实例,给子线程使用;
现在问题是:
当子线程在同时读写数据库时,主线程对数据库进行了大量的修改后,主线程会忙几秒钟。主线程恢复正常后,子线程会出现2-4条insert语句和select语句错误,错误提示都为"database is locked"。请问有什么好的方法能避免这种状况的发生吗?
我在Sqlite中使用了互斥量进行加锁和解锁;小弟分数不多,在这里全给了,忘朋友们帮帮忙,谢谢!
Sqlite多线程操作不太可靠.且效率低下,以前测试过,它只适合单机单线程的简单应用
如果你真的是用于应用而非个人测试.建议使用Embedded Firebird,它与BCB配合开发桌面应用,方便又可靠且效率是我在桌面数据库测试中最高的.
木用过Sqlite
不知道Sqlite自身有没有事物、锁的概念
不过对于数据库如MSSQL、Oracle等,最好调用数据库本身的事物和锁
Sqlite 的句柄不可以跨线程传递.
你要线程就要自己封装.
而且 这个数据库 在批量数据操作时候使用不使用事务效率相差很大
Embedded Firebird 支持SQL吗?
<
有人封装过<使用>
[打开-<使用>- 关闭]
也就是同一时刻只有一个Sqlite实例被打开. 那么正常打开退出,操作等没有异常呀什么发生,就不会在同一目录下产生一个临时文件或者rollback文件,这个时候也就不提示你锁定了.
Sqlite 自己带的事务琐 貌似不好用, 我在一个循环里面不挺的尝试上百次以后居然就进去了.
这个时候我另外一个事务 我还没有放开呢. 晕呀.
<
<
哈哈,支持SQL-99标准 就不错了. 下次我也找个项目运用一下.
而且是脱胎于Borland公司,没有理由不支持.
问这个的原因 是有个叫 Berkeley DB 的东东是API接口调用的。 不支持SQL.
它的简单的设计是通过在开始一个事务的时候锁定整个数据文件而完成的。
很容易被锁定的。
问一下楼主,问题解决了吗?
我也遇到类似问题,经常数据库会卡住很长时间,大于5分钟。
关注一下,准备用这个东东呢.
问题解决了,是资源释放的时候,没有释放干净。
sqlite3_finalize(sql_stmt);加入这条语句后就好了
给分了,参与的都有分啊,大家平分一下
这个问题我也碰到过,当时很郁闷啊,试了好多方法没有答案。
无奈换了个驱动包,问题解决,jdbcSqlite-v056.jar 好像是2.5*M的。
希望对楼主有用。
10 Jul
以下代码在C++ Builder 5.0中运行会死机,在VC6.0中运行也会死机,但是可以在VC6.0中加上编译选项/MDt(好象这样写的,记不太清楚了)就不会死机。
所以我觉得这个问题跟编译时是否用的是多线程运行时库有关,但就是不知道在C++ Builder 5.0中是否有这样的选项?
#include <windows.h>
unsigned long g_thread_num = 0; //统计线程运行的个数
bool g_run_flag = true; //控制线程的退出
HANDLE start_thread(void fn(HANDLE *))
{
HANDLE *handle;
unsigned long thread_id;
handle = (HANDLE *)malloc(sizeof(HANDLE *));
*handle = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE)fn,
handle,
0,
&thread_id
);
return *handle;
}
void malloc_free_thread(HANDLE *handle)
{
void *p;
g_thread_num++;
while(g_run_flag)
{
p = malloc(64);
free(p);
Sleep(0); //释放一下CPU,免得CPU占用率太高
}
CloseHandle(*handle);
free(handle);
g_thread_num–;
}
void main(void)
{
for(int i=0;i<100;i++)
{
//启动多个线程
start_thread(malloc_free_thread);
}
system("pause");
g_run_flag = false;
while(g_thread_num)
{
//等待线程退出
Sleep(10);
}
}
问题已解决,如果用集成环境编译,打开xxx.bpr工程文件,如果用命令行编译,打开xxx.mak文件,把其中的cw32.lib修改成cw32mt.lib就可以了。
散分吧
前的回答有点问题,更正一下:
如果用集成环境编译,打开xxx.bpr工程文件,把其中的cw32.lib修改成cw32mti.lib,
如果用命令行编译,打开xxx.mak文件,把其中的cw32.lib修改成cw32mt.lib,这样就可以了。
再多说一句,本人以前写过一些程序,在长时间运行后会发生崩溃,通过CodeGuard只看到说在调用malloc时function failure,但实际上内存还有很多,检查代码却发现不了任何问题,这个问题曾经困扰我很久,后来通过先申请一大块内存自已做内存管理才使这个问题得到规避。然后怀疑是多线程调用malloc和free时出的问题才写了以上的测试代码,果然一运行就崩溃,所以才想到C++ Builder开发工具默认没有使用多线程运行时库。
用New 和 Delete 试试
malloc、free是线程安全的。很多优秀的库是用C写的,你不用malloc、free也不行,象sqlite,所以不注意这点程序崩溃了也不知道是怎么回事。
new,delete一样会死机,因为最后调用的还是malloc、free。
<
console向导有多线程选项的
受教了。
散分吧
学习了
进来学习下….
<
路过!!
你从TThread派生出线程子类就可以了,会自动设置多线程标志,mallo与free就可以自动线程安全了。不要使用winapi,就不会有问题。
也是路过
收获不小
2 Jul
本人程序基本结构是这样:
主线程(应用程序)+子线程;主线程使用一个Sqlite实例,每启动一个子线程后子线程都会自己单独创建一个Sqlite实例,给子线程使用;
现在问题是:
当子线程在同时读写数据库时,主线程对数据库进行了大量的修改后,主线程会忙几秒钟。主线程恢复正常后,子线程会出现2-4条insert语句和select语句错误,错误提示都为"database is locked"。请问有什么好的方法能避免这种状况的发生吗?
我在Sqlite中使用了互斥量进行加锁和解锁;小弟分数不多,在这里全给了,忘朋友们帮帮忙,谢谢!
Sqlite多线程操作不太可靠.且效率低下,以前测试过,它只适合单机单线程的简单应用
如果你真的是用于应用而非个人测试.建议使用Embedded Firebird,它与BCB配合开发桌面应用,方便又可靠且效率是我在桌面数据库测试中最高的.
木用过Sqlite
不知道Sqlite自身有没有事物、锁的概念
不过对于数据库如MSSQL、Oracle等,最好调用数据库本身的事物和锁
Sqlite 的句柄不可以跨线程传递.
你要线程就要自己封装.
而且 这个数据库 在批量数据操作时候使用不使用事务效率相差很大
Embedded Firebird 支持SQL吗?
<
有人封装过<使用>
[打开-<使用>- 关闭]
也就是同一时刻只有一个Sqlite实例被打开. 那么正常打开退出,操作等没有异常呀什么发生,就不会在同一目录下产生一个临时文件或者rollback文件,这个时候也就不提示你锁定了.
Sqlite 自己带的事务琐 貌似不好用, 我在一个循环里面不挺的尝试上百次以后居然就进去了.
这个时候我另外一个事务 我还没有放开呢. 晕呀.
<
<
哈哈,支持SQL-99标准 就不错了. 下次我也找个项目运用一下.
而且是脱胎于Borland公司,没有理由不支持.
问这个的原因 是有个叫 Berkeley DB 的东东是API接口调用的。 不支持SQL.
它的简单的设计是通过在开始一个事务的时候锁定整个数据文件而完成的。
很容易被锁定的。
问一下楼主,问题解决了吗?
我也遇到类似问题,经常数据库会卡住很长时间,大于5分钟。
关注一下,准备用这个东东呢.
问题解决了,是资源释放的时候,没有释放干净。
sqlite3_finalize(sql_stmt);加入这条语句后就好了
给分了,参与的都有分啊,大家平分一下
2 Jul
本人程序基本结构是这样:
主线程(应用程序)+子线程;主线程使用一个Sqlite实例,每启动一个子线程后子线程都会自己单独创建一个Sqlite实例,给子线程使用;
现在问题是:
当子线程在同时读写数据库时,主线程对数据库进行了大量的修改后,主线程会忙几秒钟。主线程恢复正常后,子线程会出现2-4条insert语句和select语句错误,错误提示都为"database is locked"。请问有什么好的方法能避免这种状况的发生吗?
我在Sqlite中使用了互斥量进行加锁和解锁;小弟分数不多,在这里全给了,忘朋友们帮帮忙,谢谢!
Sqlite多线程操作不太可靠.且效率低下,以前测试过,它只适合单机单线程的简单应用
如果你真的是用于应用而非个人测试.建议使用Embedded Firebird,它与BCB配合开发桌面应用,方便又可靠且效率是我在桌面数据库测试中最高的.
木用过Sqlite
不知道Sqlite自身有没有事物、锁的概念
不过对于数据库如MSSQL、Oracle等,最好调用数据库本身的事物和锁
Sqlite 的句柄不可以跨线程传递.
你要线程就要自己封装.
而且 这个数据库 在批量数据操作时候使用不使用事务效率相差很大
Embedded Firebird 支持SQL吗?
<
有人封装过<使用>
[打开-<使用>- 关闭]
也就是同一时刻只有一个Sqlite实例被打开. 那么正常打开退出,操作等没有异常呀什么发生,就不会在同一目录下产生一个临时文件或者rollback文件,这个时候也就不提示你锁定了.
Sqlite 自己带的事务琐 貌似不好用, 我在一个循环里面不挺的尝试上百次以后居然就进去了.
这个时候我另外一个事务 我还没有放开呢. 晕呀.
<
<
哈哈,支持SQL-99标准 就不错了. 下次我也找个项目运用一下.
而且是脱胎于Borland公司,没有理由不支持.
问这个的原因 是有个叫 Berkeley DB 的东东是API接口调用的。 不支持SQL.
它的简单的设计是通过在开始一个事务的时候锁定整个数据文件而完成的。
很容易被锁定的。
问一下楼主,问题解决了吗?
我也遇到类似问题,经常数据库会卡住很长时间,大于5分钟。
关注一下,准备用这个东东呢.
问题解决了,是资源释放的时候,没有释放干净。
sqlite3_finalize(sql_stmt);加入这条语句后就好了
给分了,参与的都有分啊,大家平分一下
28 Apr
事情是这样的 ,我想完成大型数据的录入工作。包括对文件的存取 我是一行一行的读入。刚开始我对数据库的存取是在主线程里实现的。做过相关工作的可能知道, 当数据库录入的时候,主线程没有反映跟死机了似的 直到数据处理完毕后(大概10分钟左右)才有反映。刚开始我以为,把对数据的存储放在,子线程 一切就OK了。
我创建的线程如下
MainThread()
{
SubThread *p=new SubThread(false);
}
SubThread(…)
{
Process()
{
//大量数据的录入
}
void Execute()
{
Synchronize(Process);
}
}
可是我使用线程的情况跟不使用线程的情况是一样的 当数据处理的时候 主线程依然没有反映
我以为是文件读取延迟的速度可以我吧数据库的操作注释掉之后 发现 对文件的处理时间是很短的
我又有新的疑问是不是子线程的优先级太高了 使得主线程 对用户的响应 得不到处理啊
个人感觉这个疑问有点傻 本人新手 还请各位大侠 帮忙啊
版主好
我想请教一下在将大量数据录入数据库时,一般是走什么流程呢?
使用线程同样占用资源,如果数据一次处理比较多依然会出现当机
<
<
<