异步网络呼叫

时间:2011-07-31 10:23:44

标签: c++ qt asynchronous

我创建了一个具有异步OpenWebPage()函数的类。致电OpenWebPage(someUrl)后,系统会调用一个处理程序 - OnPageLoad(reply)。我一直在使用一个名为lastAction的全局变量来处理页面加载后的事情 - 处理程序检查lastAction是什么并调用适当的函数。例如:

this->lastAction == "homepage";
this->OpenWebPage("http://www.hardwarebase.net");

void OnPageLoad(reply)
{
     if(this->lastAction == "homepage")
     {
         this->lastAction = "login";
         this->Login();     // POSTs a form and OnPageLoad gets called again
     }
     else if(this->lastAction == "login")
     {
         this->PostLogin(); // Checks did we log in properly, sets lastAction as new topic and goes to new topic URL
     }
     else if(this->lastAction == "new topic")
     {
         this->WriteTopic(); // Does some more stuff ... you get the point
     }
}

现在,这很难写,并记录我们何时有大量“行动”。当我用Python(同步)做事时,它更容易,比如:

OpenWebPage("http://hardwarebase.net") // Stores the loaded page HTML in self.page
OpenWebpage("http://hardwarebase.net/login", {"user": username, "pw": password}) // POSTs a form
if(self.page == ...): // now do some more checks etc.
    // do something more

现在想象一下,我有一个包含动作的队列类:主页,登录,新主题。我应该如何通过异步回调执行所有这些操作(以正确的顺序,一个接一个!)?第一个例子显然是完全硬编码的。

我希望你理解我的问题,因为坦率地说我担心这是有史以来最糟糕的问题:x

P.S。所有这些都在Qt。

中完成

2 个答案:

答案 0 :(得分:1)

您需要在每个“if”分支的末尾添加“return”语句:在您的代码中,所有“if”分支都在第一个OnPageLoad调用中执行。

通常,异步状态管理总是比同步更复杂。考虑使用枚举替换lastAction类型。此外,如果OnPageLoad线程上下文是任意的,则需要同步对全局变量的访问。

答案 1 :(得分:1)

如果您尝试使用单个成员变量来维护任意数量的异步操作的状态,那么您正在邀请所有方式的错误,这就是您在上面描述的内容。您无法确定OpenWebPage调用完成的顺序,因此也无法在任何给定时间将lastAction的值与任何特定操作相关联。

有很多方法可以解决这个问题,例如:

  1. 将网页加载封装在每个实例处理一个页面的不可变类中
  2. OpenWebPage返回跟踪进度并存储操作状态的对象
  3. 操作完成时触发信号并将操作的上下文附加到信号