从workerthread中的函数到UI的后消息 [英] Postmessages from function inside workerthread to UI

查看:158
本文介绍了从workerthread中的函数到UI的后消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道我要问的事情是否可行,但请允许我描述一下.我有几个实用程序功能组合在一起可以完成一项任务.每个函数将字符串数据输出到文本文件.我想在一个工作线程中使用这些功能,并且让我的线程将消息发布到主UI富文本框中.我正在写入文本文件的相同数据.

我的问题是,在不对实用程序函数中的各处消息进行编码的情况下,实现此目标的最佳方法是什么?由于所有工作线程看到的都是"StartTask()",因此它将不知道何时将消息发布到UI.我的想法是将类的指针传递到包含字符串数据的实用程序函数,但是我仍然不知道如何在每次文本可用时如何使工作线程将消息发布到UI.

以下是一些说明:
我想添加Analysis类,该类已经具有将文本输出到文件的代码.我想找到一种在Analysis类中使用NotifyUI的方法.


在我的UI中,我有用于处理线程中的PostMessages的代码:

I don''t know if what I am asking is possible but let me see if I can describe it. I have several utility functions that are put together to do a task. Each function outputs string data to a text file. I would like to use each of these functions in a worker thread, and have my thread post messages to the main UI rich textbox. The same data I am writing to the text file.

My question is, what is the best way to implement this without coding post messages everywhere in my utility functions. Since all the worker thread sees is "StartTask()" it won''t know when to post the message to the UI. My idea was to pass the pointer of a class to the utility functions that would contain the string data, but I still don''t know how I can have the worker thread post messages to the UI everytime text is available.

Here is some more clarification:
I want to add the class Analysis which already has code to output text to a file. I want to find a way to use my NotifyUI inside the Analysis class.


In my UI I have code to handle PostMessages from my thread:

LRESULT CMappingAnalysisDialog::OnUpdateStatus(WPARAM, LPARAM lParam)
{
    // Put in shared_ptr so it is automatically destroyed.
	CString* msg = reinterpret_cast<CString*>(lParam);
	SetDlgItemText(IDC_STATIC_STATUS_TEXT, *msg);
	
	delete msg;
	return 0;
}



在我的WorkerThread中,我有:



In my WorkerThread I have:

void NotifyUI( UINT uNotificationType )
	{
		// Check if the hWnd is still valid before posting the message
		// Note: use PostMessage instead of SendMessage because PostMessage
		// performs an asynchronous post; whereas SendMessage sends synchronously
		// (sending synchronously would kind of defeat the purpose of using a
		// worker thread)
		if( ::IsWindow( m_hWnd ) )
		{
			switch( uNotificationType )
			{
			case NOTIFY_INC_PROGRESS:
				::PostMessage( m_hWnd, WM_USER_INC_PROGRESS, 0, 0);//LPARAM data goes here);
				break;
			case NOTIFY_UPDATE_STATUS_TEXT:
				::PostMessage(m_hWnd, WM_USER_UPDATE_STATUS_TEXT, 0, reinterpret_cast<LPARAM>(new CString(updateMessage)));
				break;
			case NOTIFY_UPDATE_EVENT_TEXT:
				::PostMessage( m_hWnd, WM_USER_UPDATE_EVENT_TEXT, 0, reinterpret_cast<LPARAM>(new CString(updateMessage)));
				break;
			case NOTIFY_UPDATE_OUTPUT:
				::PostMessage( m_hWnd, WM_USER_UPDATE_OUTPUT, 0, reinterpret_cast<LPARAM>(new CString(updateMessage)));
				break;
			case NOTIFY_THREAD_COMPLETED:
				::PostMessage( m_hWnd, WM_USER_THREAD_COMPLETED, 0, 0 );
				break;
			default:
				ASSERT( 0 );
			}
		}
	}







static UINT WINAPI ThreadProc( LPVOID lpContext )
	{
		// Turn the passed in ''this'' pointer back into a CMappingLog instance
		CMapFaultAnalysis* pThis = reinterpret_cast< CMapFaultAnalysis* >( lpContext );
                CAnalysis analysis;
		CString output;
		CString status;
		//Thread work
		for(int j = 0; j < 3; j++)
		{
			pThis->updateMessage = "Starting Analysis";
		        pThis->NotifyUI(NOTIFY_UPDATE_EVENT_TEXT);

			for(int i = 0; i < 20; i++)
			{
                             anaysis.RunAnalysis()
			}
		}
		//REPORT END OF THREAD
		pThis->NotifyUI(NOTIFY_THREAD_COMPLETED);
		return 1;
	}

推荐答案

我不确定我是否正确理解了您的问题.您可能希望让Windows为您执行同步,并使用工作线程中的SendMessage将显示消息发送到UI线程. Windows将使发送线程与接收线程同步.但是请注意,发送线程将阻塞,直到SendMessage返回.

针对经修正的问题进行了修正:

我会改变两件事:

(1)用SendMessage替换PostMessage调用.这样,您就可以将本地缓冲区(分配在堆栈上)用于消息字符串.这将消除使用新CString"的所有麻烦,然后将所有权传递给UI线程,最后删除UIThread中的CString.如上所述,Windows将保留您的工作线程,直到SendMessage调用返回为止,这在您的情况下是可以接受的.

(2)我将创建一个小类对象,该对象包含显示窗口的窗口句柄,并将SendMessage调用包装在成员函数中.如果愿意,您甚至可以覆盖"operator<<"并创建自己的流媒体界面.将此类对象传递给您的Analyze函数,然后您可以从那里生成日志消息.您甚至可以创建一个从同一基类派生的第二类对象,该对象将您的消息写到文件中-到目前为止您一直在做.这样,您的分析功能就无需知道日志消息的去向.您只需传递一个或另一个记录器对象即可.
I am not sure that I understood your question correctly. You might want to let Windows do the synchronization for you and use SendMessage from your worker thread to send display messages to your UI thread. The sending thread will be synchronized with the receiving thread by Windows. But be aware that the sending thread will block until SendMessage returns.

Amended in response to the amended question:

I would change two things:

(1) Replace the PostMessage calls by SendMessage. That allows you to use a local buffer (allocated on the stack) for the message string. And that will get rid of all the hassle with the "new CString", then passing ownership to the UI thread, and finally deleting the CString in the UIThread. As I said above, Windows will hold your worker thread until the SendMessage call returns, which seems acceptable in your case.

(2) I would create a small class object that holds the window handle of your display window and that wraps the SendMessage calls in a member function. If you like, you could even override "operator <<" and create your own streaming interface. Pass this class object to your Analyze function and then you can generate log messages from there. You could even create a second class object, derived from the same base class, that writes your messages into a file - as you have been doing so far. That way, your Analyze function does not need to know, where the log message go. You simple pass the one or the other logger object.


看看:
Have a look at: SendMessageCallback[^], it''s highly useful when you want to pass a dynamically allocated buffer, since you can have the callback release the memory once the message has been processed.

Best regards
Espen Harlinn


您是否想这样说..
Are you trying to say like this..
//inside thread ---
PostMessage(WM_MYMSG, 0, 0);
// and receive it inside UI in a synchronized way like this
BEGIN_MSG_MAP(MyWnd)
MESSAGE_HANDLER(WM_MYMSG, OnMymethod);
END_MSG_MAP()
//do your work inside onMymethod() function


这篇关于从workerthread中的函数到UI的后消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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