单击对话框关闭按钮时正确中止线程
Posted
技术标签:
【中文标题】单击对话框关闭按钮时正确中止线程【英文标题】:Abort thread properly when dialog box close button is clicked 【发布时间】:2013-08-10 16:39:05 【问题描述】:您好,来自 *** 的同事们!
我会尽量简短,所以我会切入正题:
我在 Windows XP 上工作,使用 C++,使用纯 Win32 创建对话框。
该对话框有一些编辑控件和确定按钮,按下时会激活一个线程。
线程然后从编辑控件中收集文本,并使用 OLE 自动化将它们写入 MS Word 文档。
一切正常,当我按下确定按钮时,等待线程显示填充的 Word 文档。
但是,当我按下 OK 按钮然后关闭对话框时,当线程在工作中时,会弹出一个空白 Word 文档。
为了进一步说明我的问题,这里有一些代码 sn-ps:
这是线程函数的sn-p:
DWORD WINAPI TabelaSvihObjekata( LPVOID hWnd ) // hWnd is handle of the Dialog box
// obtain dialogs window handle
HWND hwnd = (HWND)hWnd;
// Initialize COM for this thread...
CoInitialize(NULL);
// Get CLSID for our server...
CLSID clsid;
HRESULT hr = CLSIDFromProgID(L"Word.Application", &clsid);
// do other Automation stuff and clean afterwards
在对话框中,这是按钮处理程序的 sn-p:
case IDOK:
// create thread
DWORD threadID;
HANDLE threadHandle = CreateThread( NULL , 0 ,
(LPTHREAD_START_ROUTINE)TabelaSvihObjekata ,
(void*)hwnd , 0 , &threadID );
if( !threadHandle )
MessageBox( hwnd, L"Error", L"Error", MB_ICONERROR );
EndDialog( hwnd, IDCANCEL );
CloseHandle( threadHandle );
这是有问题的处理程序:
case IDCANCEL:
EndDialog(hwnd, IDCANCEL);
break;
我在 MSDN 上找了一个线索,发现只有 ExitThread 作为解决方案,但我不知道如何正确使用它,因为我对线程没有经验。
浏览 SO 存档,我在 C# 中找到了一些示例,人们在其中引入布尔变量并在 while 循环中测试它的值,因此他们可以确定是中止线程还是让它工作。建议另一种方式,其中线程被放置在单独的进程中,然后被杀死。
我的问题是:
我应该添加或更改什么,所以当我关闭对话框时,Word 应用程序会随着线程销毁一起关闭?
如果还有什么我可以帮忙的,请提出来,我会很乐意的。
感谢所有试图提供帮助的人。
【问题讨论】:
这可能会有所帮助:codeproject.com/Articles/552/Using-Worker-Threads 它确实给了我一些想法,但主要是在MFC中。由于我是线程的新手,所以我现在觉得比较困难,但我会一遍又一遍地重读它,希望它能帮助我解决这个问题。非常感谢您的回复! 我打算传达的主要观点是使用一个在工作线程中定期检查的布尔变量。如果您的 main/gui 线程需要停止工作,则应将布尔值设置为 false,并且您的工作人员应在下一次签入时做出适当的响应。不幸的是,在工作线程之后没有自动清理方法,因此当您的工作人员线程发现(运行 == false),如果它已经打开,它应该关闭 ms-word,然后从线程函数返回。 好吧,我就是这么理解的。所以我只需要弄清楚如何实现bool变量和abort机制。也许像这样: volatile bool SomeBool ?是否应该在对话框中声明?如果是这样,我的线程函数是否能够“看到”它?这些都是我现在面临的问题。再次感谢您的回复! volatile 关键字使得在线程之间共享布尔值是安全的。我会把布尔值放在对话框中。为了让工作线程看到它,您可以将一个指向布尔变量甚至整个对话框类的指针作为线程参数传递。请参阅教程中的“线程解决方案”部分,其中发布者将指向他的 CMyView 类的指针传递给他的线程。 【参考方案1】:如果您使用 WinApi,您必须使线程句柄可由其他代码部分访问。 然后要终止您的线程,您可以使用 ExitThread - 这是 MSDN 的首选选项。我向您展示如何使用它:
DWORD threadID;
HANDLE hthread;
void TerminateYourThread()
DWORD exitCode;
if(GetExitCodeThread(hThread,&exitCode) != 0) // check if your thread is active
ExitThread(exitCode); // terminating thread
if(CloseHandle(hThread)) // closing handle
//
void CreateYourThread()
hThread = CreateThread( NULL , 0 ,
(LPTHREAD_START_ROUTINE)TabelaSvihObjekata ,
(void*)hwnd , 0 , &threadID );
现在,当您想终止线程时,只需调用 TerminateYourThread 函数。它一直等到线程关闭。 这只是建议而不是最终解决方案,因此您可以在将来对其进行重构。
【讨论】:
好的,谢谢!我将不得不仔细研究这个 sn-p,因为我是线程新手。我们将“保持联系”,因为我会尽快报告我的进展。再次感谢! 为了澄清,ExitThread() 将退出 CALLING 线程。那么为什么要调用 GetExitCodeThread() 呢?线程不需要检查自己是否正在运行 =/ 反之,从主线程调用 ExitThread 不会有预期的效果。以上是关于单击对话框关闭按钮时正确中止线程的主要内容,如果未能解决你的问题,请参考以下文章
Datepicker:单击按钮时如何弹出日期选择器并将值存储在变量中[关闭]
单击对话框内的asp按钮时,如何防止关闭jQuery模式对话框?