您的位置:首页 > 其它

对程序驱动机制的一些理解

2012-07-05 17:02 120 查看
一个程序处于一个死循环当中,在循环中执行功能:

int main()

{

bool bQuit = false;

while(!bQuit)

{

char c = getchar();

if(c == 'q')

break;

else if( c == ...)

{

...

}

}



return 0;

}

上述给程序分配任务是通过用户输入字符完成的,在简单程序中是可以的,只要任务种类不是很多;但是如果某一天,系统功能不断扩充,功能不断增加,256个字符不足以表示所有的任务种类;这时你可以想到用int类型,足以代表相当种类的数量,也是可行方法;后来,某一天,你发现,给程序分配任务不仅仅通过人的输入,在程序执行的某一步也想要向程序下达下一步进行的任务,此时你想到能不能通过一个队列,把程序要执行的功能存储起来,每次循环中从队列中取任务来响应,任务的表示可以通过一个结构体或类来表示,那么任务的表示更加丰富,更易于扩展;所以出现了下面的模型:

int main()

{

while(1)

{

Event event = GetPendingEventFromQueue();

if (event.Quit = true)

break;



ProcessEvent(event);

}

}

void Process(Event event)

{

...

PostEventToQueue(newevent);

...

}

对列中的event可以设定优先级,实现实时处理的目的;从队列中取event后,可以将该event中队列中删除,也可以不删除;上面就是基于任务驱动的程序了;该模型中的血液中具有状态机的功能;其实程序执行流程也是从一个状态到另外一个状态的变换过程;再后来的某一天,你需要并行处理某些任务,需要启动新的线程来执行另外的功能,怎么办?只要有了队列,一切问题都可以解决,worker线程函数中只要这样:

unsigned int TreadFunction(void* arg)

{

while(1)

{

Event event = GetEventFromThreadQueue();

if(event.Quit == true)

break;



ProcessTreadEvent(event);

}

}

void ProcessTreadEvent(Event event)

{

...

//要与main线程通信,或协作完成某项任务

PostEventToMainQueue(newevent);

...

}

在main线程中,如果要worker线程执行某项任务,只要PostEventToWorkerQueue(event)即可;

main线程,与worker线程都有自己的event队列,只要不断从自己的队列中取任务,执行任务;

从上面的模型中可以得到如下结论:

main线程与worker线程都是线程,线程都应该有自己的任务队列,线程公司处在一个死循环当中,

死循环中线程从自己队列中取任务,执行任务;这种任务驱动的模型可以大大简化问题;处理复杂问题

时更得心应手;

有些同学可能会有疑问,如果我再main线程中向worker线程中投递一个event,但是我想知道该event的

执行结果后,再决定我再main线程中的下一步工作,如何处理?这个也不是问题!

方法有很多,例如回调函数,或者Future模式;

Future模式简单字面理解就是将来的事情;一个可行的实现方法是;

Future* future = PostEventToWorkerQueue(event);

bool result = future->GetReuslt();

future->release();//多线程中,一般通过引用计数来解决对象生命期问题

if(result == true)

...

else

...



void PostEventToWorkerQueue(event)

{

Future* future = new Future();

future->Increase();

event.SetFuture(future);



...

}

在Future内部可以包含一个事件(widnows中),当投递到worker线程的event处理完成后,

event可以激发Fucure内部的事件,使future->GetReuslt()内部会从阻塞的事件当中醒过来;

Future::GetResult()

{

::WaitForSingleObject(m_hEvent, INFINIT);

reutrn m_bResult;

}

计算机程序都是相同的,在操作系统内部也有个任务队列,操作系统也是在死循环当中取任务,执行任务;

所以说,把基础打好很重要,这样理解问题很透彻,深刻;

widnows程序中也有个队列,叫消息队列,在main线程中有个如下的消息循环:

while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)

{

if (bRet == -1)

{

// handle the error and possibly exit

}

else

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

}

从消息队列中取消息,然后向窗口函数派发消息;

在windows的线程中也可以有个消息队列,只需在线程函数开始出呼叫PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);这样该线程便有了个消息队列,该队列可以容纳的最大消失数目是10000;

然后线程函数中可以通过GetMessage或PeekMessage从队列中取出消息;

有了上面的了解,那么自然可以想到实践中windows中UI线程如何与workder线程通信,

通过PostMessage或PostThreadMesage;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: