rt,问题描述:
程序分为左边的Treectrl和右边的ListCtrl两部分,现在要求点击treectrl的某个节点后,通过查询数据库,将其对应的内容显示在右边的ListCtrl中,由于包含的内容比较多,所以为了让程序有较好的响应效果,我开了一个线程专门用来查询数据库,并且往listctrl中插入内容。当用户点击treectrl某个节点,线程开始查询数据库,并向listctrl中插入,如果此时用户又点击一个新节点,则正在运行的进程退出,然后新的进程开启。于是这就涉及到一个线程同步的问题,我用以下的方法://全局变量
BOOL g_end=FALSE;
HANDLE g_hThread=NULL;
//查询数据库并向listctrl中插入内容的线程
DWORD WINAPI MyThread(LPVOID lParam)
{
//查询数据库,得到数据库中记录条数count
//循环插入数据库
for (int i=0;i<count;i++)
{
if (g_end)//如果此时有新的线程要创建,则不继续往listctrl中插入
//记录,程序提前退出
{
//释放资源并退出
}
//否则向Listctrl插入下一条记录
plistctrl->InsertItem()
plistctrl->SetItem();
.... }}
//响应树视的Click事件的函数
void ***::OnClickTree(NMHDR* pNMHDR, LRESULT* pResult)
{
if (g_hThread!=NULL) //如果有线程存在,先等线程结束
{
g_end=TRUE;
WaitForSingleObject(g_hThread,INFINITEW);
CloseHandle(g_hThread);
g_hThread=NULL;
}
//然后再开始新线程
g_end=FALSE;
g_hThread=CreateThread(NULL,0,myworkthread,...,....);//创建线程}以前也类似做过,效果很好(不过以前线程是纯粹处理数据的,完全不与界面打交道),按道理来说,应该没有什么问题,但是此程序中每次到WaitForSingleObject(g_hThread,INFINITEW);都会死锁。后来考虑到是否thread里面涉及到窗口了(listctrl),而不是单纯的工作线程,而且看MSDN中有如下描述:Use caution when calling the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses a wait function with no time-out interval may cause the system to become deadlocked。不知道是否与这个原因有关,还望各位指点,谢谢了,呵呵
程序分为左边的Treectrl和右边的ListCtrl两部分,现在要求点击treectrl的某个节点后,通过查询数据库,将其对应的内容显示在右边的ListCtrl中,由于包含的内容比较多,所以为了让程序有较好的响应效果,我开了一个线程专门用来查询数据库,并且往listctrl中插入内容。当用户点击treectrl某个节点,线程开始查询数据库,并向listctrl中插入,如果此时用户又点击一个新节点,则正在运行的进程退出,然后新的进程开启。于是这就涉及到一个线程同步的问题,我用以下的方法://全局变量
BOOL g_end=FALSE;
HANDLE g_hThread=NULL;
//查询数据库并向listctrl中插入内容的线程
DWORD WINAPI MyThread(LPVOID lParam)
{
//查询数据库,得到数据库中记录条数count
//循环插入数据库
for (int i=0;i<count;i++)
{
if (g_end)//如果此时有新的线程要创建,则不继续往listctrl中插入
//记录,程序提前退出
{
//释放资源并退出
}
//否则向Listctrl插入下一条记录
plistctrl->InsertItem()
plistctrl->SetItem();
.... }}
//响应树视的Click事件的函数
void ***::OnClickTree(NMHDR* pNMHDR, LRESULT* pResult)
{
if (g_hThread!=NULL) //如果有线程存在,先等线程结束
{
g_end=TRUE;
WaitForSingleObject(g_hThread,INFINITEW);
CloseHandle(g_hThread);
g_hThread=NULL;
}
//然后再开始新线程
g_end=FALSE;
g_hThread=CreateThread(NULL,0,myworkthread,...,....);//创建线程}以前也类似做过,效果很好(不过以前线程是纯粹处理数据的,完全不与界面打交道),按道理来说,应该没有什么问题,但是此程序中每次到WaitForSingleObject(g_hThread,INFINITEW);都会死锁。后来考虑到是否thread里面涉及到窗口了(listctrl),而不是单纯的工作线程,而且看MSDN中有如下描述:Use caution when calling the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses a wait function with no time-out interval may cause the system to become deadlocked。不知道是否与这个原因有关,还望各位指点,谢谢了,呵呵
解决方案 »
- 窗体之间控制变量(control)的传值
- 请教有关Windows服务的问题,高手请进
- 如何实现一个“控制台”程序(or系统)?
- 50分求 Visual C++ 游戏编程基础 电子书
- 请问用ODBC访问access数据库时,如何查找一个时间段内的数据并对其按某项进行升降排序?
- CListCtrl如何设置选中某一行?
- 在多次调用DLL中MFC的CDialog:Create死锁?
- 用Borland C++编的程序如何用VC的编译器来编译??(请高手指点)
- mfc 如何使一个弹出的子菜单的第一项亮起
- 如何改变ListBox控件中每一行的颜色?
- 大家帮忙推荐几个小型局域网的软件防火墙,谢谢!
- 关于SetLayerWindowAttributes()函数!高手请进
要查询的内容很多:你可以获得前100条或者200条记录然后显示.处理CListCtrl滚动条事件他超过你已经查出的结果然后继续查。
DWORD WINAPI MyThread(LPVOID lParam)
{
//查询数据库,得到数据库中记录条数count
//循环插入数据库
while(true)
{
dwRst = WaitForMultipleObjects();//他的事件句柄至少有两个,1:tree点击事件,程序退出事件。
switch(dwRst)//分别处理响应的事件。
{
} // plistctrl->InsertItem() //处理点击事件的时候添加item。
// plistctrl->SetItem();
.... }}
但是还是和我说的目的有所不同啊
DWORD WINAPI MyThread(LPVOID lParam)
{
//查询数据库,得到数据库中记录条数count
//循环插入数据库
while(true)
{
dwRst = WaitForMultipleObjects();//他的事件句柄至少有两个,1:tree点击事件,程序退出事件。
switch(dwRst)//分别处理响应的事件。
{
} // plistctrl->InsertItem() //处理点击事件的时候添加item。
// plistctrl->SetItem();
.... }}是每插入一条记录就WaitForMultipleObjects();还是一次点击才WaitForMultipleObjects();啊,而且我感觉这两种情况都达不到目的啊,还望指教
当客户点击另一ITEM时,通知线程处理,在该线程中自当知道如果上次连接数据库未完成需要先取消,然后再连接新的ITEM对应的数据库,甚至如果是同一数据库,可以维持SESSION的不关闭。
还有一点,如果抛开其他思路不说,仅对于我的思路,请问应该如何做,才能解决我在上面所描述的问题呢,谢谢了
我们这样说,假设你的代码执行到WaitFor...时,你创建的线程正好执行到plistctrl->InsertItem()之前一句汇编,此时WaitFor...将阻塞GUI线程,也就意味着InsertItem这一GUI操作无法继续进行,因而线程无法退出,那么WaitFor...将永远等下去了
我从MSDN中获取这段关于MsgWaitForMultipleObjects的使用示例,希望能对你有用:
HANDLE* lphObjects, // handles that need to be waited on
int cObjects // number of handles to wait on
)
{
// The message loop lasts until we get a WM_QUIT message,
// upon which we shall return from the function.
while (TRUE)
{
// block-local variable
DWORD result ;
MSG msg ; // Read all of the messages in this next loop,
// removing each message as we read it.
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// If it is a quit message, exit.
if (msg.message == WM_QUIT)
return 1;
// Otherwise, dispatch the message.
DispatchMessage(&msg);
} // End of PeekMessage while loop. // Wait for any message sent or posted to this queue
// or for one of the passed handles be set to signaled.
result = MsgWaitForMultipleObjects(cObjects, lphObjects,
FALSE, INFINITE, QS_ALLINPUT); // The result tells us the type of event we have.
if (result == (WAIT_OBJECT_0 + cObjects))
{
// New messages have arrived.
// Continue to the top of the always while loop to
// dispatch them and resume waiting.
continue;
}
else
{
// One of the handles became signaled.
DoStuff (result - WAIT_OBJECT_0) ;
} // End of else clause.
} // End of the always while loop.
} // End of function.
WaitForSingleObject(g_hThread,INFINITEW);
CloseHandle(g_hThread);
g_hThread=NULL;
改成:
MessageLoop (&g_hThread, 1);
把 modena(非云) 的MessageLoop ()中的DoStuff (result - WAIT_OBJECT_0) ;改成:
CloseHandle(g_hThread);
g_hThread=NULL;
break;
试试看。
解决了,我怎么没有想到,呵呵,看了半天,我还以为它是个消息循环呢,呵呵,不好意思,呵呵,再次感谢你!哈哈,好高兴,这个问题一直折磨我,一直没有得到很好的解决,今天终于解决了,谢谢楼上的各位,散分了,呵呵!!