Home > database >  Basic thread management implementation from GUI - start, stop, pause
Basic thread management implementation from GUI - start, stop, pause

Time:04-20

I am searching for the common way how to manage working threads from GUI in C on the Windows platform.

The problem is simple, I have a basic user interface with 3 buttons: start, pause and stop. The first button starts a thread which looks for images in the given folder to invert their color pixel by pixel. Optionally, the user interface may display log messages generated by events from the working thread in a rectangular, uneditable text area.

One of earliest solution used in practice was described in this article: CodeProject: Using Worker Threads

The author wrote:

when you have a variable of any sort that can be modified from one thread and whose modification must be detected in another, you must declare it as volatile.

How to approach the same on more recent compilers if, say, it has no such constructs as an atomic variable.

UPDATE:

  • I'm aware of the fact that the article above is quite outdated, I thought it would be interesting for people too see how multithreading was evolved since early days. But the main reason I linked the article to this question is because of its quote, it is simple and well expressed. It formulates the frequently arising problem when I start to think about dedicated threads in my applications.
  • I do not expect in answers any concrete solution for proposed problem in C . What is the common way to approach the problem in general words? I expect this problem is quite often meet in practice in one form or another.

CodePudding user response:

You need a class which manages the thread state and of course some basic code to run a std::thread. Something like the following

#include <iostream>
#include <thread>
#include <mutex>

class Bar
{
public:

Bar() 
{
    goOn = true;
    suspended = false;
}

void worker()
{
    int count = 0;

    while (goOn)
    {
        if (!isSuspened())
        {
            std::cout << "counting ... " << count << '\n';
            count  ;
        }
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

bool isSuspened()
{
    std::lock_guard<std::mutex> lock(mtx);
    return suspended;
}
void suspend(bool b)
{
    std::lock_guard<std::mutex> lock(mtx);
    suspended = b;
}

void terminate()
{
    std::lock_guard<std::mutex> lock(mtx);
    goOn = false;
}

private:
 bool goOn;
 bool suspended;

 std::mutex mtx;
};

int main()
{
Bar bar;

// Create and execute the thread
std::thread thread(&Bar::worker, &bar); // Pass 10 to member function

std::string asw;

while (true)
{
    std::cout << "Enter 's' to suspend the thread, 'r' to resume or 't' to terminate: ";
    std::cin >> asw;
    if (asw == "s")
        bar.suspend(true);
    else if (asw == "r")
        bar.suspend(false);
    else if (asw == "t")
    {
        bar.terminate();
        break;
    }
}

thread.join();

return 0;
}

Note the usage of std::mutex to synchronize the access to the variables controlling the execution of the thread. This is important to avoid strange behaviour due to concurrent access to the variables from tdifferent threads

CodePudding user response:

Look at the example code for std::stop_token. It requires C 20, but see how simple it is with standard C now. you can even omit the join; std::jthread does join upon destruction.

  • Related