bcb多线程 处理大数据量

时间:2023-01-18 21:12:05
我试着做了一个多线程,主程序没问题,但是另一个线程,处理数据比较多,10秒一个循环处理一次,一次大约1700多条数据,所以,运行多线程的时候,程序会假死,也就是“无响应”,而此时,这个假死,会导致主程序也假死,导致主程序不在独立运行,只有在多线程完成每次循环间隙才执行。新手的悲剧啊

各位大侠如何解决啊,,,,新手呜呜。。。。。。。
或者有更好的方法!!!!!

6 个解决方案

#1


详细说明你是怎么做的,别人才知道哪里出了问题。
我怀疑你其实用的是Timer而不是多线程。

#2


//主程序开始就启动线程
void __fastcall TMainForm::FormShow(TObject *Sender)
{
        //多LED刷新第一个页面
        TimerPageChangeTimer(Sender);
        
        LEDDataBufferThread->Resume();
}

//线程部分(里面的循环,每次循环都在2000数据左右)
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "LEDDataBufferUnit.h"       
#include "datamodule.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 LEDDataBuffer::UpdateCaption()
//      {
//        Form1->Caption = "Updated in a thread";
//      }
//---------------------------------------------------------------------------

__fastcall LEDDataBuffer::LEDDataBuffer(bool CreateSuspended)
        : TThread(CreateSuspended)
{
        //Timer1->Interval=10000;
}
//---------------------------------------------------------------------------
/*
void __fastcall LEDDataBuffer::Timer1Timer(TObject *Sender)
{
        //Synchronize(ExecSQL);
}
*/
void __fastcall LEDDataBuffer::ExecSQL()
{
        sql="select L.BufferID,T.* from (select showno,count(showno)as [Count] from LEDDataBuffer \
        group by showno having count(showno) >1)T join LEDSendData L on T.ShowNo=L.ShowNo";
        DataModule1->show(sql,DataModule1->ADOQLEDDataBufferThirdShow);
        //循环检索这个区域在缓存的数据
        while(!DataModule1->ADOQLEDDataBufferThirdShow->Eof)
        {
                //检索1--检索按照ID排序大约正在播放ID的数据
                sql="select top 1* from LEDDataBuffer where ShowNo="+DataModule1->ADOQLEDDataBufferThirdShow->FieldByName("ShowNo")->AsString+" \
                and ID>"+DataModule1->ADOQLEDDataBufferThirdShow->FieldByName("Bufferid")->AsString;
                DataModule1->show(sql,DataModule1->ADOQLEDDataBufferThirdShow1);
                //检索1---无结果--表示已经是最后一个了,要返回到第一个数据
                if(DataModule1->ADOQLEDDataBufferThirdShow1->Eof)
                {
                        //检索2---检索这个区域在缓存的第一个数据
                        sql="select top 1* from LEDDataBuffer where ShowNo="+DataModule1->ADOQLEDDataBufferThirdShow->FieldByName("ShowNo")->AsString+"\
                        order by ID asc";
                        DataModule1->show(sql,DataModule1->ADOQLEDDataBufferThirdShow1);
                        if(DataModule1->ADOQLEDDataBufferThirdShow1->Eof)
                        {
                                //检索2---无结果--表示已经是已经没有数据,返回空!!
                                sql="select top 1 0 as ID ,'' as ShowNo,'' as SendData,'红色' as Color from LEDDataBuffer ";
                                DataModule1->show(sql,DataModule1->ADOQLEDDataBufferThirdShow1);
                        }


                }
                //将检索的数据更新到发送表,并将发送状态改为“未发送”
                sql="update LEDSendData set SendData='"+DataModule1->ADOQLEDDataBufferThirdShow1->FieldByName("SendData")->AsString+"',\
                FontColor='"+DataModule1->ADOQLEDDataBufferThirdShow1->FieldByName("Color")->AsString+"',\
                Bufferid="+DataModule1->ADOQLEDDataBufferThirdShow1->FieldByName("ID")->AsString+",IsSend=0 \
                where Showno="+DataModule1->ADOQLEDDataBufferThirdShow->FieldByName("ShowNo")->AsString;
                DataModule1->exec(sql,DataModule1->ADOQLEDDataBufferThirdExec);

                ::Sleep(1000);
                DataModule1->ADOQLEDDataBufferThirdShow->Next();
        }
}
void __fastcall LEDDataBuffer::Execute()
{
        //---- Place thread code here ----
        //Timer1->OnTimer=Timer1Timer;
        while(!Terminated)
        {
                Synchronize(ExecSQL);
                ::Sleep(10000);
        }

}
//---------------------------------------------------------------------------

#3


 Synchronize(ExecSQL);的问题,应该把你ExecSQL函数中需要显示的数据保存在线程类的成员变量中,先直接调用ExecSQL获得数据,之后再用Synchronize调用另一个函数,这个函数负责根据在ExecSQL中设置的变量显示数据,如果数据量太多,可以考虑分成多次显示,在ExecSQL函数中,取得一批数据用Synchronize调用显示函数显示一次。你这样的做法相当于单线程

#4


倒地吐血不止, bcb多线程 处理大数据量你的线程里面只执行了sleep,ExecSQL因为Synchronize是在主线程执行了。
你试一试在线程里直接执行ExecSQL

void __fastcall LEDDataBuffer::Execute()
{
        while(!Terminated)
        {
                ExecSQL();
                ::Sleep(10000);
        }

}

#5


楼上说的对,是的,虽然Synchronize是bcb提供的一个安全访问,但并不能使线程严格区分执行。4#的方法可以一试。不过我还是建议使用CreateThread创建线程:

CreateThread(NULL,0,ThreadProc,NULL,NULL,NULL);

第一个参数是指向安全属性的指针,NULL就行
第二个参数是初始线程堆栈大小,0就可以,WINDOWS会自动分配
第三个参数指向线程函数,必须是这样DWORD WINAPI ThreadProc (LPVOID pParam) 
第四个参数是传给线程函数的参数,有就传,没有就NULL
第五个参数是线程启动方式,可以是挂起CREATE_SUSPENDED,或者马上启动NULL
最后一个参数是创建的线程ID。

成功的话,返回线程句柄。

#6


主线程只负责创建线程类,至于说是用CreateThread或者是用TThread类都可以。本质没有什么区别,推荐用Thread比较好,没有什么特殊用途的话很烦方便。

一般的做法是:
主线程创建线程类,热按后Resume() 在子线程中运行需要处理的函数,然后中间使用消息进行通讯。比如主线程需要显示一些子线程中的提示等,防止子线程出错而没法响应。

楼主的主要工作其实还是在主线程中执行,在执行数据操作的时候,主界面的消息循环处于等待状态,当然就会没有响应了。如果完全采用子线程操作,原则上来说只和cpu的处理能力有关了。

#1


详细说明你是怎么做的,别人才知道哪里出了问题。
我怀疑你其实用的是Timer而不是多线程。

#2


//主程序开始就启动线程
void __fastcall TMainForm::FormShow(TObject *Sender)
{
        //多LED刷新第一个页面
        TimerPageChangeTimer(Sender);
        
        LEDDataBufferThread->Resume();
}

//线程部分(里面的循环,每次循环都在2000数据左右)
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "LEDDataBufferUnit.h"       
#include "datamodule.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 LEDDataBuffer::UpdateCaption()
//      {
//        Form1->Caption = "Updated in a thread";
//      }
//---------------------------------------------------------------------------

__fastcall LEDDataBuffer::LEDDataBuffer(bool CreateSuspended)
        : TThread(CreateSuspended)
{
        //Timer1->Interval=10000;
}
//---------------------------------------------------------------------------
/*
void __fastcall LEDDataBuffer::Timer1Timer(TObject *Sender)
{
        //Synchronize(ExecSQL);
}
*/
void __fastcall LEDDataBuffer::ExecSQL()
{
        sql="select L.BufferID,T.* from (select showno,count(showno)as [Count] from LEDDataBuffer \
        group by showno having count(showno) >1)T join LEDSendData L on T.ShowNo=L.ShowNo";
        DataModule1->show(sql,DataModule1->ADOQLEDDataBufferThirdShow);
        //循环检索这个区域在缓存的数据
        while(!DataModule1->ADOQLEDDataBufferThirdShow->Eof)
        {
                //检索1--检索按照ID排序大约正在播放ID的数据
                sql="select top 1* from LEDDataBuffer where ShowNo="+DataModule1->ADOQLEDDataBufferThirdShow->FieldByName("ShowNo")->AsString+" \
                and ID>"+DataModule1->ADOQLEDDataBufferThirdShow->FieldByName("Bufferid")->AsString;
                DataModule1->show(sql,DataModule1->ADOQLEDDataBufferThirdShow1);
                //检索1---无结果--表示已经是最后一个了,要返回到第一个数据
                if(DataModule1->ADOQLEDDataBufferThirdShow1->Eof)
                {
                        //检索2---检索这个区域在缓存的第一个数据
                        sql="select top 1* from LEDDataBuffer where ShowNo="+DataModule1->ADOQLEDDataBufferThirdShow->FieldByName("ShowNo")->AsString+"\
                        order by ID asc";
                        DataModule1->show(sql,DataModule1->ADOQLEDDataBufferThirdShow1);
                        if(DataModule1->ADOQLEDDataBufferThirdShow1->Eof)
                        {
                                //检索2---无结果--表示已经是已经没有数据,返回空!!
                                sql="select top 1 0 as ID ,'' as ShowNo,'' as SendData,'红色' as Color from LEDDataBuffer ";
                                DataModule1->show(sql,DataModule1->ADOQLEDDataBufferThirdShow1);
                        }


                }
                //将检索的数据更新到发送表,并将发送状态改为“未发送”
                sql="update LEDSendData set SendData='"+DataModule1->ADOQLEDDataBufferThirdShow1->FieldByName("SendData")->AsString+"',\
                FontColor='"+DataModule1->ADOQLEDDataBufferThirdShow1->FieldByName("Color")->AsString+"',\
                Bufferid="+DataModule1->ADOQLEDDataBufferThirdShow1->FieldByName("ID")->AsString+",IsSend=0 \
                where Showno="+DataModule1->ADOQLEDDataBufferThirdShow->FieldByName("ShowNo")->AsString;
                DataModule1->exec(sql,DataModule1->ADOQLEDDataBufferThirdExec);

                ::Sleep(1000);
                DataModule1->ADOQLEDDataBufferThirdShow->Next();
        }
}
void __fastcall LEDDataBuffer::Execute()
{
        //---- Place thread code here ----
        //Timer1->OnTimer=Timer1Timer;
        while(!Terminated)
        {
                Synchronize(ExecSQL);
                ::Sleep(10000);
        }

}
//---------------------------------------------------------------------------

#3


 Synchronize(ExecSQL);的问题,应该把你ExecSQL函数中需要显示的数据保存在线程类的成员变量中,先直接调用ExecSQL获得数据,之后再用Synchronize调用另一个函数,这个函数负责根据在ExecSQL中设置的变量显示数据,如果数据量太多,可以考虑分成多次显示,在ExecSQL函数中,取得一批数据用Synchronize调用显示函数显示一次。你这样的做法相当于单线程

#4


倒地吐血不止, bcb多线程 处理大数据量你的线程里面只执行了sleep,ExecSQL因为Synchronize是在主线程执行了。
你试一试在线程里直接执行ExecSQL

void __fastcall LEDDataBuffer::Execute()
{
        while(!Terminated)
        {
                ExecSQL();
                ::Sleep(10000);
        }

}

#5


楼上说的对,是的,虽然Synchronize是bcb提供的一个安全访问,但并不能使线程严格区分执行。4#的方法可以一试。不过我还是建议使用CreateThread创建线程:

CreateThread(NULL,0,ThreadProc,NULL,NULL,NULL);

第一个参数是指向安全属性的指针,NULL就行
第二个参数是初始线程堆栈大小,0就可以,WINDOWS会自动分配
第三个参数指向线程函数,必须是这样DWORD WINAPI ThreadProc (LPVOID pParam) 
第四个参数是传给线程函数的参数,有就传,没有就NULL
第五个参数是线程启动方式,可以是挂起CREATE_SUSPENDED,或者马上启动NULL
最后一个参数是创建的线程ID。

成功的话,返回线程句柄。

#6


主线程只负责创建线程类,至于说是用CreateThread或者是用TThread类都可以。本质没有什么区别,推荐用Thread比较好,没有什么特殊用途的话很烦方便。

一般的做法是:
主线程创建线程类,热按后Resume() 在子线程中运行需要处理的函数,然后中间使用消息进行通讯。比如主线程需要显示一些子线程中的提示等,防止子线程出错而没法响应。

楼主的主要工作其实还是在主线程中执行,在执行数据操作的时候,主界面的消息循环处于等待状态,当然就会没有响应了。如果完全采用子线程操作,原则上来说只和cpu的处理能力有关了。