VC多线程访问数据库的数据传递问题

VC多线程访问数据库的数据传递问题,第1张

说一些概念性的东西吧。
COM *** 作,它有一套自己关于跨线程和跨进程的模型,这是个复合模型,会衍生出大约7,8种组合。学习COM,这个是一定要吃透的。楼主阅读一下关于CoInitializeEx函数的帮助文档,能多多少少体会到一些。但如果没学习过COM,光看MSDN的帮助文档,如坠云里雾里一般,很难理解的。因此,建议买本COM的书,稍微参阅一下,其次网上譬如CSDN中有很多热心人写的关于线程进程有关的COM模型,和使用规则,优缺点,可以拜读一下!
在MFC中,可能不太会形成跨线程传递变量的危害性,这种观念吧。所以,在MFC中,似乎我们能随心所欲在线程之间传递变量,但其实是不对的,典型的就是主线程创建的窗口和控件,最好不要在其它线程中直接 *** 纵,而是通过线程间通信的方法,让创建窗口和控件的主线程来 *** 纵窗口和控件。
因此,变量是不能乱传地,到了COM中,这个限制是非常明显的,COM中有概念叫MARSHAL、PROXY、STUB,当然它主要是进程相关的概念,同样说明了,非线程自己创建的东西,不是该线程使用就会有问题。
像VIEW这种界面的东西不要随便乱传给工作线程这种非界面线程。
我的建议是:
建工作线程,因为数据库 *** 作及从数据库反馈到程序级的数据需要进行再加工,这些步骤都可能会非常耗时,耗时 *** 作放在界面线程,会使界面线程无法处理WM_XXX的消息,造成界面假死。因此,像智能指针这种东西放到工作线程里进行独立管理,工作线程通过智能指针向数据库要数据,然后处理,存放数据结果到程序中约定的地方,如全局变量,虚拟内存等地方。数据处理完,通过自定义消息,向界面线程发送自定义消息,使界面线程能够在自定义消息中,将保存的数据显示到界面中,发送线程消息有个函数就是PostThreadMessage。
其他的细微细节也可以考虑,到底是创建自己的线程,还是使用线程池等。随着经验的丰富,会考虑很多问题的,关键是理论知识要学,实践也不能没有。
最后就是概念修正, _ConnectionPtr它是一个标准的C++类,C++类可以重载-> *** 作符,这个被重载的指针 *** 作符,使得通过该类实例化的变量在实际使用时,行为更像是一个指针,而不是个普通变量,这个被重载的指针 *** 作符才是智能指针,而不是指_ConnectionPtr类是智能指针,顶多说它是个智能指针类,我也见过有翻译成灵巧指针的,英文原版是SMART POINTER。

我也碰到过这个问题,不是 *** 作串口而是USB。
解决方式是把前台工作和后台工作分开。用MFC的CWinThread创建个后台线程(可处理消息循环,方便和前台交互)。关于CWinThread的用法自己看下,需要注意的是在前台窗口退出前必须终止后台线程,不然会出问题。
用单纯的工作线程也可,效率可能会高些,
因不处理消息循环,但和前台同步时有些不直接,要用信号量什么的。
下面是CWinThread的框架,CSDN上某兄台的帖子。(再次提醒,数据 *** 作时间长时,框架中的终止线程的方法不好使)
h
文件
#define
WM_TEST
WM_USER
+
1
class
CTestThread
:
public
CWinThread
{
DECLARE_DYNCREATE(CTestThread)
protected:
CTestThread
();
virtual
~CTestThread
();
public:
virtual
BOOL
InitInstance();
virtual
int
ExitInstance();
protected:
afx_msg
void
OnTest(WPARAM
wParam,LPARAM
lParam);
DECLARE_MESSAGE_MAP()
};
Cpp
文件
#include
"stdafxh"
#include
"TestThreadh"
IMPLEMENT_DYNCREATE(CTestThread,
CWinThread)
CTestThread::CTestThread()
{
}
CTestThread::~CTestThread()
{
}
BEGIN_MESSAGE_MAP(CTestThread,
CWinThread)
ON_THREAD_MESSAGE(WM_TEST,OnTest)
END_MESSAGE_MAP()
BOOL
CTestThread::InitInstance()
{
return
TRUE;
}
int
CTestThread::ExitInstance()
{
return
CWinThread::ExitInstance();
}
void
CTestThread::OnTest(WPARAM
wParam,LPARAM
lParam)
{
AfxMessageBox("test");
}
调用的地方
CWinThread
m_pThrd;
//启动
m_pThrd
=
AfxBeginThread(RUNTIME_CLASS(CTestThread));
//
需要执行线程中的 *** 作时
m_pThrd->PostThreadMessage(WM_TEST,NULL,NULL);
//
结束线程
HANDLE
hp=m_pThrd->m_hThread;
if
(hp)
{
if
(WaitForSingleObject(hp,
1)
!=
WAIT_OBJECT_0)
{
TerminateThread(hp,0);
}
CloseHandle(hp);
}

线程简单来说就是一个函数,添加一个静态的全局函数DWORD WINAPI ThreadProc( void pData ) ,这个函数只有一个参数,可以转换为你想要的类型。
然后在启用线程的地方添加 CreateThread( NULL, 0, ThreadProc, this, 0, NULL );
该线程函数完成后,自动退出。

线程的回调函数本是一个全局或静态的函数,他不能 *** 作其他类中的数据,在线程回调函数中定义类的对象也只能使用共有成员,
如果定义一个全局的变量的话就未免没必要,
你可以这样,
你在创建线程的时候,创线程的函数中除了回调函数参数,还有另一个参数是作为传进线程里面的参数,当你需要 *** 作类中的成员,就把那他的地址做为参数,或着直接就把类的this指针做参数,这样你在回调函数中就可以直接 *** 作回调函数的参数,就是 *** 作你建线程时候给的参数,
但在回调函数中要进行强制转换,
就是你线程函数中的那个LPVOID类型的参数,用来转换。
当然,你还可以用向主窗口发送消息的方式去使主窗口的数据有改变,
比如自定消息和处理函数,在处理函数中写你需要做的事情,而这个事情是由线程来触发的,这样不就可以线程处理数据了

楼主,传递结构体指针时注意,由于是线程执行,你可以想一下,如果你传递的是一个函数内部的局部变量,这个变量会在这个函数结束后就释放,那么你启动的线程函数中,所指向的就没有意义了。记住这是多线程执行的,不是单线程。
所以楼主,你要确定你传递结构体是个全局变量。
由于你只是代码片段,所以,看不来。自己看下。

可以这样做:
为线程参数定义一个结构体
struct threadParam
{
HANDLE self;
HANDLE other;
//还可以定义一些其他你认为需要的参数
};

//假设有2个线程A、B
HANDLE HA = new HANDLE;
HANDLE HB = new HANDLE;

threadParam pA = new threadParam;
PA->self = HA;
PA->other = HB;

HA = createthread(NULL,funcA,PA,);

将PA做为参数传递给线程A。这样就可以在线程函数里通过指针使用a,b的线程句柄了。
同样创建b线程的时候这样做一遍就ok。

不知道这样说明白否?


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/12596430.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2025-08-26
下一篇2025-08-26

发表评论

登录后才能评论

评论列表(0条)

    保存