如何在应用程序中休眠/等待而不会使UI无响应



我正在开发一个应用程序的Windows在Visual c++,这将从一个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有一个完整的事件处理系统事件系统

最新更新