延迟函数使 openFrameworks window 冻结,直到指定的时间过去

Delay function makes openFrameworks window freeze until specified time passes

我有顶点网络,我想每秒更改它们的颜色。我尝试使用 Sleep() 函数并且当前使用不同的延迟函数但两者都给出相同的结果 - 可以说我想用 1 秒的暂停将 10 个顶点着色为红色。当我开始项目时,window 似乎冻结了 10 秒,然后显示每个顶点都已经是红色了。

这是我的更新功能。

void ofApp::update(){
    for (int i = 0; i < vertices.size(); i++) {
        ofColor red(255, 0, 0);
        vertices[i].setColor(red);
        delay(1);
    }
}

这里是绘制函数

void ofApp::draw(){
    for (int i = 0; i < vertices.size(); i++) {
        for (int j = 0; j < G[i].size(); j++) {
            ofDrawLine(vertices[i].getX(), vertices[i].getY(), vertices[G[i][j]].getX(), vertices[G[i][j]].getY());
        }
        vertices[i].drawBFS();
    }
}

    void vertice::drawBFS() {
    ofNoFill();
    ofSetColor(_color);
    ofDrawCircle(_x, _y, 20);
    ofDrawBitmapString(_id, _x - 3, _y + 3);
    ofColor black(0, 0, 0);
    ofSetColor(black);
}

这是我的 delay() 函数

void ofApp::delay(int number_of_seconds) {
    // Converting time into milli_seconds 
    int milli_seconds = 1000 * number_of_seconds;

    // Stroing start time 
    clock_t start_time = clock();

    // looping till required time is not acheived 
    while (clock() < start_time + milli_seconds)
        ;
}

你的代码没有错误,只是对等待的误解。所以这不是确定的答案,只是正确方向的提示。

您可能只有一个线程。一个线程一次只能做一件事。当您调用 delay 时,这个线程所做的就是一遍又一遍地检查时间,直到某个时间过去。

在此期间线程不能做任何事情(它不能神奇地跳过指令或检测你的意图)。所以它不能发出绘图命令或交换一些缓冲区来在屏幕上显示矢量。这就是您的应用程序似乎冻结的原因——99.9% 的时间它都在检查间隔是否已过。这也给 cpu.

带来了沉重的负担

解决方案可能有点棘手并且需要线程。通常你有一个 UI-Thread 定期绘制东西,刷新显示,可能需要输入等等。此线程永远不应进行繁重的计算以保持 UI 响应。然后,第二个线程将管理更繁重的计算或更新数据。

如果你想运行一个时间间隔内的任务,你不只是循环直到时间结束,但本质上"tell the OS"第二个线程应该在一段时间内不活动。 OS 将比实施主动等待更有效地管理这种方式。

但这是一个很大的话题,所以我建议您继续阅读有关多线程的内容。自 C++11 以来,C++ 有一个 small thread library。可能值得一看。

// .h
float nextEventSeconds = 0;

// .cpp
void ofApp::draw(){
    float now = ofGetElapsedTimef();
    if(now > nextEventSeconds) {
        // do something here that should only happen
        // every 3 seconds
        nextEventSeconds = now + 3;
    }
}

按照这个例子,我设法解决了我的问题。