简体   繁体   中英

Delay function makes openFrameworks window freeze until specified time passes

I have network of vertices and I want to change their color every second. I tried using Sleep() function and currently using different delay function but both give same result - lets say I want to color 10 vertices red with 1 second pause. When Im starting project it seems like the window freezes for 10 seconds and then shows every vertice already with red color.

This is my update function.

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

Here is draw function

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);
}

This is my delay() function

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)
        ;
}

There is no bug in your code, just a misconception about waiting. So this is no definitive answer, just a hint in the right direction.

You have probably just one thread. One thread can do exactly one thing at a time. When you call delay all this one thread is doing is checking the time over and over again until some time has passed.

During this time the thread can do nothing else (it can not magically skip instructions or detect your intentions). So it can not issue drawing commands or swap some buffers to display vectors on screen. That's the reason why you application seems to freeze - 99.9% of the time it's checking if the interval has passed. This also places a heavy load on the cpu.

The solution can be a bit tricky and requires threading. Usually you have a UI-Thread that regularly draws stuff, refreshes the display, maybe takes inputs and so on. This thread should never do heavy calculations to keep the UI responsive. A second thread will then manage heavier calculations or updating data.

If you want to run a task in an interval you don't just loop until the time is over, but essentially "tell the OS" that the second thread should be inactive for a certain period. The OS will manage this way more efficient than implementing active waiting.

But that's quite a large topic, so I suggest you read on about Multithreading. C++ has a small thread library since C++11. May be worth a look.

// .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;
    }
}

Following this example I managed to solve my problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM