wxWidget中的线程编程模型? Topic is solved

这是wxWidgets论坛的中文版本。在这里,您可以用您的母语汉语讨论上面任一子论坛所涉及的所有关于wxWidgets的话题。欢迎大家参与到对有价值的帖子的中英互译工作中来!
Post Reply
Justin2008
Earned a small fee
Earned a small fee
Posts: 14
Joined: Thu Mar 06, 2008 2:10 am

wxWidget中的线程编程模型?

Post by Justin2008 »

我想使用一个线程来实现较长时间的计算,并用一个进度条来显示计算进度,该如何设计呢?wxWidget自带的例子看的不是很明白,感觉把计算和界面类耦合的太厉害,可能自己对wxWidget的线程模型不了解才有这样的感觉,有谁能说说线程模型吗?
Utensil
Moderator
Moderator
Posts: 423
Joined: Sun Feb 03, 2008 11:38 am
Location: China

Post by Utensil »

你是指wxWidgets/samples/thread下的例子吧?我个人觉得挺清晰的啊~

不过它把所有代码写到一个文件里是有些混乱,你可以把代码折叠起来看。

按你的要求,主要看类MyWorkerThread。它边工作,边把进度存放在它创建的一个事件里,发送给主进程,wxProgressDialog收到这个事件就会作出回应。

这是一种推荐的线程更新GUI的做法,用事件。另外一种方式是wxMutexGuiEnter()和wxMutexGuiLeave(),MyThread类使用了这种方式。

-Utensil
In fascination of creating worlds by words, and in pursuit of words behind the world.

On Github: http://utensil.github.com
Technical Blog in Chinese: http://utensil.iteye.com/
Justin2008
Earned a small fee
Earned a small fee
Posts: 14
Joined: Thu Mar 06, 2008 2:10 am

Post by Justin2008 »

类MyWorkerThread中的Entry函数

Code: Select all

void *MyWorkerThread::Entry()
{
	for ( m_count = 0; !m_frame->Cancelled() && (m_count < 100); m_count++ )
	{
		// check if we were asked to exit
		if ( TestDestroy() )
			break;

		// create any type of command event here
		wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, WORKER_EVENT );
		event.SetInt( m_count );

		// send in a thread-safe way
		wxPostEvent( m_frame, event );

		// wxSleep() can't be called from non-main thread!
		wxThread::Sleep(200);
	}

	wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, WORKER_EVENT );
	event.SetInt(-1); // that's all
	wxPostEvent( m_frame, event );

	return NULL;
}
代码中可以看出,它的计算时间是可以实现确定的。如果我的计算时间无法实现确定,如何显示进度?
此外,我在计算完之后需要利用计算后的数据创建一个新的窗口,但是我的数据没计算完,窗口就显示了。如何利用线程保证数据计算完之后再显示窗口?
Utensil wrote:你是指wxWidgets/samples/thread下的例子吧?我个人觉得挺清晰的啊~

不过它把所有代码写到一个文件里是有些混乱,你可以把代码折叠起来看。

按你的要求,主要看类MyWorkerThread。它边工作,边把进度存放在它创建的一个事件里,发送给主进程,wxProgressDialog收到这个事件就会作出回应。

这是一种推荐的线程更新GUI的做法,用事件。另外一种方式是wxMutexGuiEnter()和wxMutexGuiLeave(),MyThread类使用了这种方式。

-Utensil
liuqi5521
Earned some good credits
Earned some good credits
Posts: 103
Joined: Thu Apr 03, 2008 5:35 am
Location: China
Contact:

嗯。

Post by liuqi5521 »

其实较长时间的操作要想显示进度也不一定要用多线程的。
我是VB转过来的,喜欢用DoEvents,嗬嗬,单线程配合DoEvents一样好使。

可以参考我写的一个拷贝文件并且显示进度,还可以响应其他消息的例子代码:
http://forums.wxwidgets.org/viewtopic.php?t=18836
Justin2008
Earned a small fee
Earned a small fee
Posts: 14
Joined: Thu Mar 06, 2008 2:10 am

Re: 嗯。

Post by Justin2008 »

我看了一下你的代码,与Windows平台相关了,不过使用时间器的确是个选择。
liuqi5521 wrote:其实较长时间的操作要想显示进度也不一定要用多线程的。
我是VB转过来的,喜欢用DoEvents,嗬嗬,单线程配合DoEvents一样好使。

可以参考我写的一个拷贝文件并且显示进度,还可以响应其他消息的例子代码:
http://forums.wxwidgets.org/viewtopic.php?t=18836
Utensil
Moderator
Moderator
Posts: 423
Joined: Sun Feb 03, 2008 11:38 am
Location: China

Post by Utensil »

代码中可以看出,它的计算时间是可以实现确定的。如果我的计算时间无法实现确定,如何显示进度?
代码里哪里确定时间了? 你能够确定百分比,就能够显示进度了。

如果你是说那个 wxThread::Sleep(200),那你就误会了,因为这个线程什么都不干,它不加这句话,它就瞬间结束了。你可以把它置换为任何需要耗费时间的计算过程。
此外,我在计算完之后需要利用计算后的数据创建一个新的窗口,但是我的数据没计算完,窗口就显示了。如何利用线程保证数据计算完之后再显示窗口?


你可以参照代码中的方法,在线程结束时,把一个不寻常的整数(如-8)放进事件里,然后再在主程序的事件处理那边作专门处理。

-Utensil
In fascination of creating worlds by words, and in pursuit of words behind the world.

On Github: http://utensil.github.com
Technical Blog in Chinese: http://utensil.iteye.com/
liuqi5521
Earned some good credits
Earned some good credits
Posts: 103
Joined: Thu Apr 03, 2008 5:35 am
Location: China
Contact:

Post by liuqi5521 »

嗯,DoEvents确实调用Win32API了
liuqi5521
Earned some good credits
Earned some good credits
Posts: 103
Joined: Thu Apr 03, 2008 5:35 am
Location: China
Contact:

如果你的计算时间确实无法确定

Post by liuqi5521 »

如果你的计算时间确实无法确定,那么你可以用进度条的脉动模式啊,就是Pulse方法。
Justin2008
Earned a small fee
Earned a small fee
Posts: 14
Joined: Thu Mar 06, 2008 2:10 am

Post by Justin2008 »

我的代码将计算和创建新窗口都放在一个线程内,窗口显示不正确。
难道必须这样设计:将计算放在线程里,在线程结束后在显示新窗口?
Utensil wrote:
代码中可以看出,它的计算时间是可以实现确定的。如果我的计算时间无法实现确定,如何显示进度?
代码里哪里确定时间了? 你能够确定百分比,就能够显示进度了。

如果你是说那个 wxThread::Sleep(200),那你就误会了,因为这个线程什么都不干,它不加这句话,它就瞬间结束了。你可以把它置换为任何需要耗费时间的计算过程。
此外,我在计算完之后需要利用计算后的数据创建一个新的窗口,但是我的数据没计算完,窗口就显示了。如何利用线程保证数据计算完之后再显示窗口?


你可以参照代码中的方法,在线程结束时,把一个不寻常的整数(如-8)放进事件里,然后再在主程序的事件处理那边作专门处理。

-Utensil
Utensil
Moderator
Moderator
Posts: 423
Joined: Sun Feb 03, 2008 11:38 am
Location: China

Post by Utensil »

你把你的代码(相关的部份)贴上来看一看?应该显示正确的,我就在线程里弹出过窗口。

-Utensil
In fascination of creating worlds by words, and in pursuit of words behind the world.

On Github: http://utensil.github.com
Technical Blog in Chinese: http://utensil.iteye.com/
Justin2008
Earned a small fee
Earned a small fee
Posts: 14
Joined: Thu Mar 06, 2008 2:10 am

Re: 如果你的计算时间确实无法确定

Post by Justin2008 »

脉动模式的特点是什么?我感觉挺怪的,每一次移动的好慢 :(
liuqi5521 wrote:如果你的计算时间确实无法确定,那么你可以用进度条的脉动模式啊,就是Pulse方法。
Justin2008
Earned a small fee
Earned a small fee
Posts: 14
Joined: Thu Mar 06, 2008 2:10 am

Post by Justin2008 »

由于组里有规定不能展现代码,所以。。。
我刚才按照你说的试了一下,在线程中计算,计算完成之后,发送事件,在事件相应函数中来显示窗口,总算基本可以了。不知道,你的思路是不是这样?

谢谢你的建议。(有人讨论真好,周围没人使用wxWidget,快把我郁闷死了)
Utensil wrote:你把你的代码(相关的部份)贴上来看一看?应该显示正确的,我就在线程里弹出过窗口。

-Utensil
liuqi5521
Earned some good credits
Earned some good credits
Posts: 103
Joined: Thu Apr 03, 2008 5:35 am
Location: China
Contact:

Re: 如果你的计算时间确实无法确定

Post by liuqi5521 »

Justin2008 wrote:脉动模式的特点是什么?我感觉挺怪的,每一次移动的好慢 :(
liuqi5521 wrote:如果你的计算时间确实无法确定,那么你可以用进度条的脉动模式啊,就是Pulse方法。
每次调用Pulse确实移动的很小。但如果你调用多次,就会移动的很多
for(long i=0;i<20;i++)
wxGuage1->Pulse();

不要仅仅把一句放在那里,应该用一个循环
Post Reply