Visual c++ 如何在应用程序中睡眠/等待而不使UI无响应 我正在开发一个Visual C++的Windows应用程序,它将从Web API中获取输入。一些API调用要求我在指定的时间延迟内请求响应,在此期间,我希望显示一个微调器

Visual c++ 如何在应用程序中睡眠/等待而不使UI无响应 我正在开发一个Visual C++的Windows应用程序,它将从Web API中获取输入。一些API调用要求我在指定的时间延迟内请求响应,在此期间,我希望显示一个微调器,visual-c++,Visual C++,我对显示微调器、禁用按钮等都很在行,但我不知道如何在应用程序中暂停进程。显然,如果我使用\u sleep功能,应用程序将变得不可用 这里或多或少是我需要实现的(伪代码) 实现我所需的正确方法是什么?您很可能只想轮询web API的响应,或者您可以启动辅助线程来检查web API的响应 在看到一些最小的代码之后,类似的东西可能会起作用 //takes an initial start time, calculates elapsed time, compares elapsed time to

我对显示微调器、禁用按钮等都很在行,但我不知道如何在应用程序中暂停进程。显然,如果我使用
\u sleep
功能,应用程序将变得不可用

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


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

您很可能只想轮询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;
    }
}

如果每秒运行函数
foo::update()
,则可以相应地更改时间间隔。这里是对另一个类的引用,这可能很有趣,更不用说,QT有一个完整的事件处理系统

我们谈论的延迟有多长,毫秒还是秒?可能有几个选项,很可能您希望定期读取系统时间,并且在经过一定时间后检查是否有来自web api的响应。您也可以在一个单独的工作线程中检查响应—通常我们说的是几十秒(10-30秒),但我发送给API的一个作业可能需要几分钟(取决于可用资源—从几秒到5分钟),所以对于这一个,我需要查询响应,就像循环中每10秒一次一样。因为这些时间很长,我不想让应用程序没有响应。因为这些时间很长,你能在一个循环中运行你的整个ui,然后在循环结束时检查一次响应,一旦其他所有事情都处理好了吗?您是否可以在希望接收数据时设置一个标志,然后在首先处理ui组件之后检查是否接收到数据?线程通常会生成更复杂的ui,但如果您不需要额外的功能,这可能是一个简单的解决方案。正确,这里没有理由使用专用线程。只需使用post-an事件到事件循环,时间为30秒。如果我记得的话,“VisualC++”实际上是CLR/CLI,它基本上是围绕MFC的薄型包装,不是吗?这就是您正在使用的UI框架吗?非常感谢您的提示-我会查看它。无论如何,我是否能够从另一个线程访问UI元素(例如,启用返回按钮)?如果它们是全局定义的,则不会有任何问题,尽管在多个线程之间访问相同数据时必须小心,以避免争用情况。如果这是您感兴趣的内容,那么也可以看看std::mutex。您所说的“全局”是指它们属于同一类就足够了,还是说它们必须在整个项目中是全局的?你知道,如果我得到API的回复,我只想启用按钮,这样就不会有其他线程访问相同数据的风险。对不起,这些是我用C++的第一步,所以学习曲线很陡峭……就像从任何正则函数中访问数据一样,你可以把参数传递给函数或者使用整个项目可见的全局对象。上面的代码仍然会使应用程序反应迟钝,不是吗?一般来说,我会向API发送两个请求:第一个请求在云上创建一个资源,需要几秒钟到5分钟(取决于可用资源)——我想每隔10秒发送一个查询,看看资源是否准备就绪;第二个启动一个端点(这需要30秒),所以我会调用我的函数,至少在30秒后将任务发送到端点。
//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;
    }
}
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &foo::update);
timer->start(1000);