第一个问题是点击关闭窗口没有反应:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
DWORD tid;
DWORD exitCode = 0;
hRequestExitEvent = CreateEvent(NULL,true,false,NULL);
if(!hcd)
hcd = CreateThread(NULL,0,ListFile,(void *)this,0,&tid);
else
{
SetEvent(hRequestExitEvent); //外部终止工作线程
CloseHandle(hcd) ;
hcd = 0;
hcd = CreateThread(NULL,0,ListFile,(void *)this,0,&tid); //线程重新启动
}
while(!quit)
{
MSG msg;
DWORD result;
result = MsgWaitForMultipleObjects(1,&hcd,false, 3000, QS_ALLINPUT);
if(result == WAIT_OBJECT_0 + 1)
{
while(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message == WM_QUIT) //就是这里,如果是关闭窗口的消息就退出while
{
quit = true;
exitCode = msg.wParam;
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
if (WaitForSingleObject(hcd,INFINITE)==WAIT_OBJECT_0)
{
CloseHandle(hcd);
hcd = 0;
break;
}
}
}
}
线程函数:
unsigned long WINAPI TForm1::ListFile(void * CallPam)
{
TForm1 *tem = (TForm1 *)CallPam;
int i = 0;
while(i++ < 10000)
{
tem->Memo1->Lines->Add(IntToStr(i));
if(WaitForSingleObject(tem->hRequestExitEvent,0) != WAIT_TIMEOUT)
{
tem->Edit1->Text = "Received reauest to terminate";
return DWORD(-1);
}
}
return 0;
}
代码就是这样的了。
而且我在C++Builder中重载了WndProc函数捕捉WM_QUIT消息也是同样的问题。
第二个问题:在下面这段代码中
if(!hcd)
hcd = CreateThread(NULL,0,ListFile,(void *)this,0,&tid);
else
{
SetEvent(hRequestExitEvent); //外部终止工作线程
CloseHandle(hcd) ;
hcd = 0;
hcd = CreateThread(NULL,0,ListFile,(void *)this,0,&tid); //线程重新启动
}
我想达到的目的是:如果工作线程正在运行则停止该线程,并重新启动线程(因为变量改变了,需要重新工作),但是好象没有能够立即启动,也就是说else里的hcd = CreateThread(NULL,0,ListFile,(void *)this,0,&tid);没有产生效果,但确实是执行到了。请问这是怎么回事啊。
我一会再到VC中试试。但本人VC不熟,所以还请各位高手包涵了。
很急,谢谢了!
10 个解决方案
#1
直接一点,用TerminateThread终止了那个线程算了。
#2
确定你的线程结束了
#3
线程确实是结束了
但是窗口要关闭两次才能关掉
但是窗口要关闭两次才能关掉
#4
关闭两次,关闭是怎么处理的
#5
C++ builder中的APPLICATION也有窗体,是不可见的.
#6
第一个问题:
if(msg.message == WM_QUIT)
{
quit = true;
exitCode = msg.wParam;
break;
}
当程序获得WM_QUIT消息时,被你的这个消息循环截获了,于是你break了这个while消息循环,但是问题是系统的另外那个消息循环并没有停止,继续在运行。这就是为什么需要关闭两次才可以的原因。
你试试这样修改:
if(msg.message == WM_QUIT)
{
quit = true;
exitCode = msg.wParam;
PostMessage(hwnd, msg, NULL, NULL); // 手工添加一个QUIT消息,终止系统消息循环。
break;
}
if(msg.message == WM_QUIT)
{
quit = true;
exitCode = msg.wParam;
break;
}
当程序获得WM_QUIT消息时,被你的这个消息循环截获了,于是你break了这个while消息循环,但是问题是系统的另外那个消息循环并没有停止,继续在运行。这就是为什么需要关闭两次才可以的原因。
你试试这样修改:
if(msg.message == WM_QUIT)
{
quit = true;
exitCode = msg.wParam;
PostMessage(hwnd, msg, NULL, NULL); // 手工添加一个QUIT消息,终止系统消息循环。
break;
}
#7
第二个问题:
hRequestExitEvent = CreateEvent(NULL,true,false,NULL);
你的Event对象是手工复位的(CreateEvent的第二个参数是true),这意味你的Event对象如果不手工调用 ResetEvent函数,会一直处于激发状态。
也就是说,你创建的第二个线程在运行后,检测到hRequestExitEvent的状态是激发态后马上就退出了,这也就是为什么第二个线程没有起作用的原因。
你可以试试这样修改:
hRequestExitEvent = CreateEvent(NULL,false,false,NULL);
但是这样仍然有问题:因为你不能够确定到底是哪一个线程先被分配到时间片。所以唯一的解决方案还是老老实实等待第一个线程退出后在Create第二个线程(记得如果是在UI线程中,一定使用MsgWaitForMultipleObjects函数)
hRequestExitEvent = CreateEvent(NULL,true,false,NULL);
你的Event对象是手工复位的(CreateEvent的第二个参数是true),这意味你的Event对象如果不手工调用 ResetEvent函数,会一直处于激发状态。
也就是说,你创建的第二个线程在运行后,检测到hRequestExitEvent的状态是激发态后马上就退出了,这也就是为什么第二个线程没有起作用的原因。
你可以试试这样修改:
hRequestExitEvent = CreateEvent(NULL,false,false,NULL);
但是这样仍然有问题:因为你不能够确定到底是哪一个线程先被分配到时间片。所以唯一的解决方案还是老老实实等待第一个线程退出后在Create第二个线程(记得如果是在UI线程中,一定使用MsgWaitForMultipleObjects函数)
#8
谢谢shootingstars(有容乃大,无欲则刚)的解答,已经搞定
但仍然不大理解你第二个问题的意思:"因为你不能够确定到底是哪一个线程先被分配到时间片".这句话什么意思。
但仍然不大理解你第二个问题的意思:"因为你不能够确定到底是哪一个线程先被分配到时间片".这句话什么意思。
#9
如果按照shootingstars(有容乃大,无欲则刚)的说法。
如果我想实现立即结束线程并重新启动,就没有其它办法了吗?难道非得要等待第一个线程结束?
如果我想实现立即结束线程并重新启动,就没有其它办法了吗?难道非得要等待第一个线程结束?
#10
但仍然不大理解你第二个问题的意思:"因为你不能够确定到底是哪一个线程先被分配到时间片".这句话什么意思。
---------------------------------------------------------------------
比如你的主线程是0号线程,原来启动的那个线程是1号线程,新启动的是2号线程.
在你执行完SetEvent(hRequestExitEvent); 这个语句的若干毫秒内,CPU会切换到1号或者2号线程。(注意:CreateThread建立线程后,新建立的线程并不一定会马上得到运行的时间)。如果CPU切换到2号线程,这个结果是你不想看到的。
如果你确实不想等待第一个线程结束后再启动第二个线程,你或许可以用一个Event数组?每个Event对应一个线程。(记得在线程退出之前关闭对应的Event)
---------------------------------------------------------------------
比如你的主线程是0号线程,原来启动的那个线程是1号线程,新启动的是2号线程.
在你执行完SetEvent(hRequestExitEvent); 这个语句的若干毫秒内,CPU会切换到1号或者2号线程。(注意:CreateThread建立线程后,新建立的线程并不一定会马上得到运行的时间)。如果CPU切换到2号线程,这个结果是你不想看到的。
如果你确实不想等待第一个线程结束后再启动第二个线程,你或许可以用一个Event数组?每个Event对应一个线程。(记得在线程退出之前关闭对应的Event)
#1
直接一点,用TerminateThread终止了那个线程算了。
#2
确定你的线程结束了
#3
线程确实是结束了
但是窗口要关闭两次才能关掉
但是窗口要关闭两次才能关掉
#4
关闭两次,关闭是怎么处理的
#5
C++ builder中的APPLICATION也有窗体,是不可见的.
#6
第一个问题:
if(msg.message == WM_QUIT)
{
quit = true;
exitCode = msg.wParam;
break;
}
当程序获得WM_QUIT消息时,被你的这个消息循环截获了,于是你break了这个while消息循环,但是问题是系统的另外那个消息循环并没有停止,继续在运行。这就是为什么需要关闭两次才可以的原因。
你试试这样修改:
if(msg.message == WM_QUIT)
{
quit = true;
exitCode = msg.wParam;
PostMessage(hwnd, msg, NULL, NULL); // 手工添加一个QUIT消息,终止系统消息循环。
break;
}
if(msg.message == WM_QUIT)
{
quit = true;
exitCode = msg.wParam;
break;
}
当程序获得WM_QUIT消息时,被你的这个消息循环截获了,于是你break了这个while消息循环,但是问题是系统的另外那个消息循环并没有停止,继续在运行。这就是为什么需要关闭两次才可以的原因。
你试试这样修改:
if(msg.message == WM_QUIT)
{
quit = true;
exitCode = msg.wParam;
PostMessage(hwnd, msg, NULL, NULL); // 手工添加一个QUIT消息,终止系统消息循环。
break;
}
#7
第二个问题:
hRequestExitEvent = CreateEvent(NULL,true,false,NULL);
你的Event对象是手工复位的(CreateEvent的第二个参数是true),这意味你的Event对象如果不手工调用 ResetEvent函数,会一直处于激发状态。
也就是说,你创建的第二个线程在运行后,检测到hRequestExitEvent的状态是激发态后马上就退出了,这也就是为什么第二个线程没有起作用的原因。
你可以试试这样修改:
hRequestExitEvent = CreateEvent(NULL,false,false,NULL);
但是这样仍然有问题:因为你不能够确定到底是哪一个线程先被分配到时间片。所以唯一的解决方案还是老老实实等待第一个线程退出后在Create第二个线程(记得如果是在UI线程中,一定使用MsgWaitForMultipleObjects函数)
hRequestExitEvent = CreateEvent(NULL,true,false,NULL);
你的Event对象是手工复位的(CreateEvent的第二个参数是true),这意味你的Event对象如果不手工调用 ResetEvent函数,会一直处于激发状态。
也就是说,你创建的第二个线程在运行后,检测到hRequestExitEvent的状态是激发态后马上就退出了,这也就是为什么第二个线程没有起作用的原因。
你可以试试这样修改:
hRequestExitEvent = CreateEvent(NULL,false,false,NULL);
但是这样仍然有问题:因为你不能够确定到底是哪一个线程先被分配到时间片。所以唯一的解决方案还是老老实实等待第一个线程退出后在Create第二个线程(记得如果是在UI线程中,一定使用MsgWaitForMultipleObjects函数)
#8
谢谢shootingstars(有容乃大,无欲则刚)的解答,已经搞定
但仍然不大理解你第二个问题的意思:"因为你不能够确定到底是哪一个线程先被分配到时间片".这句话什么意思。
但仍然不大理解你第二个问题的意思:"因为你不能够确定到底是哪一个线程先被分配到时间片".这句话什么意思。
#9
如果按照shootingstars(有容乃大,无欲则刚)的说法。
如果我想实现立即结束线程并重新启动,就没有其它办法了吗?难道非得要等待第一个线程结束?
如果我想实现立即结束线程并重新启动,就没有其它办法了吗?难道非得要等待第一个线程结束?
#10
但仍然不大理解你第二个问题的意思:"因为你不能够确定到底是哪一个线程先被分配到时间片".这句话什么意思。
---------------------------------------------------------------------
比如你的主线程是0号线程,原来启动的那个线程是1号线程,新启动的是2号线程.
在你执行完SetEvent(hRequestExitEvent); 这个语句的若干毫秒内,CPU会切换到1号或者2号线程。(注意:CreateThread建立线程后,新建立的线程并不一定会马上得到运行的时间)。如果CPU切换到2号线程,这个结果是你不想看到的。
如果你确实不想等待第一个线程结束后再启动第二个线程,你或许可以用一个Event数组?每个Event对应一个线程。(记得在线程退出之前关闭对应的Event)
---------------------------------------------------------------------
比如你的主线程是0号线程,原来启动的那个线程是1号线程,新启动的是2号线程.
在你执行完SetEvent(hRequestExitEvent); 这个语句的若干毫秒内,CPU会切换到1号或者2号线程。(注意:CreateThread建立线程后,新建立的线程并不一定会马上得到运行的时间)。如果CPU切换到2号线程,这个结果是你不想看到的。
如果你确实不想等待第一个线程结束后再启动第二个线程,你或许可以用一个Event数组?每个Event对应一个线程。(记得在线程退出之前关闭对应的Event)