异步

我以前很排斥异步调用,一看到异步调用就觉得特别扭:同步调用多好,一步步地执行,一异步程序的运行顺序不大直观。可是近段时间有了新的体会,觉得有时异步真有它的好处。记下来,作个备忘。

         先要说说那个让我觉得非得用异步调用不行的场景吧。这涉及到Command模式,为了对一个业务逻辑建模我写了一大堆Command,并把这此Command加到一个队列中。每次从这个队列中取出一个来执行。类图如下:

 

 

Continue函数的实现看起来像这样:

 

        m_pCurCommand= m_queueCommands.Dequeue();

         if(NULL!= m_ pCurCommand)

         {

                   m_pCurCommand->Execute();                          //(1)

                 ……..

                   m_pCurCommand->Other();                               //(2)

         }

现在问题来了,因为某个Command的Execute方法有点复杂,对它的调用引发了CommandQueue的Continue的另一次执行,而恰好这个Command在某些情况下是最后一个Command。这样第一次执行Continue时,刚执行到(1),这时Continue开始第二次执行,并将m_pCurCommand设为了NULL,返回。第一个Continue继续,运行到(2)时,程序挂掉了!!!

 

        也许有的人会说你用个局部变量代替m_pCurCommand不好了,不幸的是。我有可能需要在外部查询当前正在执行的命令。

 

所以在这里我用上了异步调用。方法很简单我把这个Continue的实现弄成了异步,也就是说Continue会直接返回,在返回之前会将一个help function : _Continue加到一个计时器中,让_Continue在一定时间之后再执行。如下:

Void Continue()

{

         AddTimer(_Continue,1000);    //execute after 1 seconds

}

而_Continue的实现完全是将早先Continue的实现剪切下来的。

 

 

这个场景对大家来说可能不好理解,一个更通常的场景是 Socket 和客户端 Client:

 

在Client的OnRead中会调用Socket中的Read方法,Read成功的时候会返回Read到了多少数据。但是也可能会失败,失败时Socket会调用OnError。这样,如果在Client的OnError的实现中作了某些清理工作,当Read继续运行就可能会挂!!fix方法就是殷OnError弄成异步的。

 

 

 

Notice: 如果在异步调用中要传递指针,这个指针最好是个智能指针,因为你是异步,在你还没有执行的时候,那个指针可能在别的地方被人给delete了。

posted @ 2010-12-06 09:04  李书淦  阅读(571)  评论(1编辑  收藏  举报