需要正确创建,中止和关闭此类线程的说明 [英] Instructions needed to create,abort and close this kind of thread properly

查看:68
本文介绍了需要正确创建,中止和关闭此类线程的说明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有保存按钮的对话框。



单击该按钮时,我应该使用数据库中的数据填充excel。



为此,我从这里修改了代码: http://support.microsoft.com / kb / 216686 [ ^ ],套房我的用途。



问题是这个操作很长,并且不允许用户在完成之前使用GUI。



这就是为什么我决定将Excel自动化放在线程函数中,并在单击保存按钮时启动线程。



之前,我已经在CP上发布了关于多线程的问题,但已经决定远离它,因为我没经验。



我决定在线程时隐藏Save按钮正在运行,以防止多次点击产生其他线程一个保存按钮。



这将确保只有一个线程在运行,并且会避免线程同步。



我已经创建了如上所述的Excel自动化的线程函数,并且它可以工作。



问题是僵尸进程可以出现(Excel没有如果用户通过关闭对话框或关闭程序来中断线程执行。



这是我的问题:



如何关闭对话框/主窗口并正确中止线程,这样就不会出现僵尸进程?



我在Windows XP上工作MS Visual C ++和纯Win32 API(无MFC)。



注意:



这是我的意思到目前为止:



我的线程功能:

I have a dialog box with a Save button.

When that button is clicked, I should populate excel with data from database.

To do that, I have modified code from here: http://support.microsoft.com/kb/216686[^], which suites my purposes .

The problem is that this operation is lengthy and doesn’t allow user to use GUI until it is finished.

That is why I have decided to put Excel automation in a thread function, and to launch thread when Save button is clicked.

Earlier, I have posted here on CP, questions about multithreading, but have decided to stay away from it, since I am inexperienced.

I have decided to hide the Save button while thread is running, to prevent other threads being spawned with multiple clicks on a Save button.

This will ensure that there will be only one thread running, and will avoid thread synchronization.

I have created thread function which does the Excel automation as above, and it works.

The problem is that zombie process can appear ( Excel doesn’t close ) if the user interrupts thread execution by closing the dialog box, or closing the program.

That is my problem:

How to close dialog box/main window and to abort thread properly, so the zombie process does not appear ?

I work on Windows XP using MS Visual C++ and pure Win32 API ( no MFC ).

NOTE:

Here is what I have so far:

My thread function:

struct ThreadData
{
	HWND hDlg; // handle of a dialog box
	int PrimaryKey; // so I can query database
};

DWORD WINAPI MyThread( LPVOID lp )
{
	ThreadData* td = (ThreadData*)lp;

	wchar_t query[100];

	swprintf_s( query, 100, 
		L"select * from MyTable where Primary_Key = %d ;",
		td->PrimaryKey);

	HRESULT hr;

	try
	{
		CoInitialize(NULL);

		hr = // open database and perform query;

		// populate Excel as described in article

		// perform cleanup

		return 0;
	}
	catch( _comm_error & ) // no need to display textual messages , just cleanup
	{
		// do cleanup

		return 1;
	}
}





对话框摘要:



Dialog box snippet:

INT_PTR CALLBACK DialogBoxProcedure(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
	static ThreadData td;

	HANDLE threadHandle = NULL;

	static int primaryKey; // we get this value from combo box

	 switch(Message)
	 {
	 case WM_COMMAND:
		{
		    switch(LOWORD(wParam))
		    {
		     case IDCANCEL:
				
                        if( threadHandle )
		        {
			    WaitForSingleObject( threadHandle, INFINITE );

			    CloseHandle( threadHandle );
		        }

			DestroyWindow(hwnd);

			break;

		    case IDC_BUTTON1:
			{
				ShowWindow( GetDlgItem( hwnd, IDC_SAVE ), 
                                           SW_HIDE ); 

				td.hwnd = hwnd;
				td.PrimaryKey = primaryKey;

				// create thread

				DWORD threadID;

				threadHandle = CreateThread( NULL,
                                                   0,
                                                   MyThread,
                                                   (void*)&td,
                                                   0,
                                                   &threadID );
								
				if( !threadHandle )
				{
				    MessageBox( hwnd, L"Error", L"Error",
                                               MB_ICONERROR );

				    DestroyWindow(hwnd);
			        }
						
			}
			break;
		    }
		}
	// other messages
	}
// other stuff in dialog procedure
}





重要更新:



Excel生成代码也是如此大,但由于我有一个类似的线程填充预定义的Word文档,这里是该线程程序的链接,因为中止机制实际上是相同的:



< a href =http://pastebin.ca/2441960> http://pastebin.ca/2441960 [ ^ ]

推荐答案

如果线程包含阻塞函数调用,则无法关闭/终止线程。您必须向线程发送信号,然后您必须等待它正常退出。你不能从另一个线程中正确地完成/杀死一个线程,而不会对过程状态造成严重损坏并且不会泄漏。



之前,我已经在CP上发布了这个帖子,关于多线程的问题,但已经决定远离它,因为我没经验。

而你仍然缺乏经验,你会一次又一次地问同样的问题而缺乏经验。多线程并非一直是玫瑰,有时候没有很好的解决方案。您必须等待工作线程上的阻塞函数调用才能完成。期。无法立即终止某个线程,有时线程会终止几秒钟,具体取决于它执行的函数调用以及它检查取消/退出请求标志的时间。在一些函数调用的情况下,有平台/ api特定的技巧可以从根本上加速线程终止,但由于我们对try块中的代码没有任何线索我们无法帮助。



顺便说一句,以前你对你的问题得到了相当好的答案(分步说明),答案与这个同样的问题相同:延迟WM_CLOSE以便我可以让线程正常退出 [ ^ ]



你不会得到更好的答案。如果您对多线程没有任何线索但想要编写多线程应用程序,那么学习多线程。
You can not close/terminate a thread especially if it contains blocking function calls. You have to send a signal to the thread and then you have to wait for it to exit gracefully. You can not finish/kill a thread properly from another thread without causing possibly serious damage to the process state and without leaks.

"Earlier, I have posted here on CP, questions about multithreading, but have decided to stay away from it, since I am inexperienced."
And you are still inexperienced and you will remain inexperienced by asking the same question again and again. Multithreading is not roses all the way and sometimes there are no very good solutions. You have to wait your blocking function calls on your worker thread to finish. Period. No way to kill a thread instantly, sometimes a thread is terminating for seconds depending on the function calls it performs and the period in which it checks your cancel/exit request flag. In case of some function calls there are platform/api specific tricks that can radically speed up thread termination but since we have no clue about the code inside your try block we can not help in that.

BTW, previously you got fairly good answers to your question (with step-by-step instructions) and the answers are the same to this very same question: Delaying WM_CLOSE so I can allow threads to exit gracefully[^]

You won't get better answers. If you have no clue about multithreading but you want to write multithreading applications then learn multithreading.


我会创建一个(手动重置)事件(参见 http://www.youtube.com/watch?v=d9AsH5i5nJ8 [ ^ ]),在创建线程之前,但线程也可以访问,我想在早期终止线程时设置(例如,单击取消时 - 等待单个对象之前;或者在关闭事件中等等)。然后在线程本身我会定期检查事件是否设置,以适当的规则间隔(再次使用等待事件上的单个对象,但是有0次),如果设置了,如果可能的话,优雅地退出线程执行任何需要的回滚。



是否有足够的帮助让你入门?



(您也可以使用布尔值而不是事件,因为设置和检查布尔值是一个单独的操作,因此应该是有效的线程安全的,但是一个也设计为线程安全的事件更适合线程模型。例如,你可以使用wait来创建一个周期性线程 - 一个循环但是线程有效地休眠一段时间的作业 - 或者你可以使用等待多个对象的作业等待多于事件或对象的作业功能等等。)



问候,

Ian。
I would create a (manual reset) event (see http://www.youtube.com/watch?v=d9AsH5i5nJ8[^]), before creating the thread, but which the thread can also access, which I would "set" when wanting to terminate the thread early (e.g. when cancel is clicked - before the wait for single object; or in the close event, etc). Then in the thread itself I would be regularly checking that the event is not set, at suitable regular intervals (again using wait for single object on the event, but with 0 time) and if it is set, exit the thread gracefully, if possible performing any "rollback" that is needed.

Is that enough help to get you started?

(You could also use a Boolean instead of an event, since setting and checking a Boolean is a single operation so should be effectively thread safe, but an event, which are also designed to be thread safe, fit more nicely into the threading model. E.g. you can use the wait to create a "periodic thread" - a job that loops but where the thread effectively "sleeps" for a time - or you could have jobs that wait on more than on event or object using the wait for multiple objects function, etc, etc).

Regards,
Ian.


这篇关于需要正确创建,中止和关闭此类线程的说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆