微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在不使 UI 无响应的情况下在应用程序中休眠/等待

如何解决如何在不使 UI 无响应的情况下在应用程序中休眠/等待

我正在用 Visual C++ 开发一个适用于 Windows 的应用程序,该应用程序将从 Web API 获取输入。一些 API 调用要求我在某个指定的时间延迟内请求响应,在此期间我想显示一个微调器。

我对显示微调器、禁用按钮等都很好,我需要在继续请求之前等待,但不知道如何在应用程序中暂停该过程。显然,如果我使用 _sleep 函数,应用会变得无响应。

这或多或少是我需要实现的(伪代码

void doSomething()
{
   ui->button1->setEnable(false);
   SendAPIReuqest1();

   while (APIRequest1_success)
   {
      requestAPIRequest1_response();
      //wait 10s if false and retry,this can take up to 5mins
   }

   SendAPIRequest2();
   //wait 30s - here I kNow I can start the job on my end exactly after 30s

   doSometing2();
   ui->button1->setEnable(true);
}

实现我所需要的正确方法是什么?

解决方法

您很可能只想轮询来自 Web API 的响应,或者您可以启动辅助线程来检查来自 Web API 的响应;

在看到一些最少的代码后,类似的东西可能会起作用。

//takes an initial start time,calculates elapsed time,compares  elapsed time to count
bool ready(std::chrono::time_point<std::chrono::system_clock>&start,const double& count) {
    auto end = std::chrono::system_clock::now();
    std::chrono::duration<double> diff = end-start;
    if (diff.count() >= count) {
        start = end;
        return true;
    }
    return false;
} 

void doSomething()
{
    static std::chrono::time_point<std::chrono::system_clock> start;
    static int state = 0;
    switch(state) {
    case (0):
        ui->button1->setEnable(false);
        SendAPIRequest1();
        if (APIRequest1_success) {
            start = std::chrono::system_clock::now();
            ++state;
        }
        break;
    case (1):
        if (ready(start,10.0) && requestAPIRequest1_response()) ++state;
        break;
    case(2):
        SendAPIRequest2();
        start = std::chrono::system_clock::now();
        ++state;
        break;
    case(3):
        if (ready(start,30.0)) {
            doSomething2();
            ui->button1->setEnable(true);
            state = 0;
         }
         break;
    }
}

通过这种方式,您可以调用该函数,它会尝试其中一个请求或返回执行其他任务。

或者使用线程,它可以像

一样简单
void worker_func(std::promise<bool>&& result) {
    using namespace std::chrono_literals;
    SendAPIRequest1();
    while (!requestAPIRequest1_response()) {
        std::this_thread::sleep_for(10s);
    }
    SendAPIRequest2();
    std::this_thread::sleep_for(30s);
    doSomething2();
    result.set_value(true);
}

void doSomething() {
    static std::future<bool> finished;
    static bool flag = true;
    if (flag) {
        std::promise<bool> _finished;
        finished = _finished.get_future();
        ui.button1.setEnable(false);
        std::thread worker(worker_func,std::move(_finished));
        flag = false;
    } else if (finished.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
        //finished.get();
        worker.join();
        ui.button1.setEnable(true);
        flag = true;
    }
}

这样您的主线程就可以继续运行 ui,而工作线程则等待 Web API 响应,只要您的请求不处理任何 QT ui 组件,我相信这应该可行。

编辑:

由于我从未使用过 QT 并且最初从未提到正在使用 QT,因此上述答案可能有用也可能没有用,但是看起来 QT 有一些功能可以处理此类事情。也许你可以启动和停止一个 Qtimer

QTimer *timer = new QTimer(this);
connect(timer,&QTimer::timeout,this,&foo::update);
timer->start(1000);

每秒运行一次函数foo::update(),时间间隔可以相应地改变。这里是对 QTimer 的引用和对另一个可能感兴趣的类的引用 QTimerEvent 更不用说,QT 有一个完整的事件处理系统 The Event System

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。