如何解决如何在不使 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 举报,一经查实,本站将立刻删除。