The thread does not want to finish because of the “TestDestroy” always return false.

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
User avatar
lionking
Earned a small fee
Earned a small fee
Posts: 17
Joined: Sun Apr 07, 2019 6:07 pm

The thread does not want to finish because of the “TestDestroy” always return false.

Post by lionking » Mon Jan 13, 2020 3:10 am

This is the first time I have used threads and after I read a little from the documentation on threads I am still confused.
in my example, I want to do a very simple example just Increasing a progress bar (wxGauge) to reach 100% by using a thread.

Code: Select all

// mainFrm.cpp (Main Window)

void mainFrm::button_OnClick(wxCommandEvent & event) {
    thread = new CThread;
    if (thread->Run() != wxTHREAD_NO_ERROR) {
        wxLogError("Can't create the thread!");
        delete thread;
        thread = NULL;
    }
}
// CThread.cpp

CThread::CThread() : wxThread(wxTHREAD_DETACHED) {
}

Code: Select all

wxThread::ExitCode CThread::Entry() {
    int counter = 0;
    progressbar = (wxGauge*)wxWindow::FindWindowByName("progressbar");
    button = (wxButton*)wxWindow::FindWindowByName("button");
    textbox = (wxTextCtrl*)wxWindow::FindWindowByName("textbox");
    button->Enable(false);
    while (!TestDestroy()) {
        while (counter <= 100) {
            progressbar->SetValue(counter);
            counter += 10;
            textbox->SetValue(wxString::Format("%i", progressbar->GetValue()));
            wxThread::Sleep(200);
        }
    }
    button->Enable(true);
    wxMessageOutputDebug().Printf("%s", "The operation was compeleted.");
    return (wxThread::ExitCode)0;
}
Also, another code without using GUI (the same problem is still):

Code: Select all

wxThread::ExitCode CThread::Entry() {
    int counter = 0;
    while (!TestDestroy()) {
        while (counter <= 100) {
            counter += 10;
            wxMessageOutputDebug().Printf("%i", counter);
            wxThread::Sleep(200);
        }
        wxMessageOutputDebug().Printf("%i", this->IsAlive()); // prints "1"
    }
    wxMessageOutputDebug().Printf("%s", "The operation was compeleted.");
    return (wxThread::ExitCode)0;
}
The problem is that it does not want to come out of "while (!TestDestroy())" loop, so, the thread continues and does not finish.

Is there something wrong with my code?

User avatar
doublemax
Moderator
Moderator
Posts: 14621
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: The thread does not want to finish because of the “TestDestroy” always return false.

Post by doublemax » Mon Jan 13, 2020 6:15 am

First of all: You're not allowed to make GUI calls from inside a secondary thread, so you'll need a different approach for something like this. The sample code in the documentation shows how: https://docs.wxwidgets.org/trunk/classwx_thread.html

Regarding the TestDestroy(): This will only return true after you call wxThread::Delete, usually you do this from the main thread in order to stop the thread while it's still running. If you have job that just does a limited amount of work, you can exit the loop as soon as it's done.
Use the source, Luke!

User avatar
lionking
Earned a small fee
Earned a small fee
Posts: 17
Joined: Sun Apr 07, 2019 6:07 pm

Re: The thread does not want to finish because of the “TestDestroy” always return false.

Post by lionking » Mon Jan 13, 2020 7:12 am

Thank you for your response.
Unfortunately, I have seen that documentation link before and still don't understand it well.
If you answer my following questions you will facilitate me to understand some things that I don't understand.

After I call wxThread::Delete from outside a runtime error occurred "Read access violation".
is that error because I use wxTHREAD_DETACHED kind but when using wxTHREAD_JOINABLE wxThread::Delete will be worked fine, right?

Also, when using wxThread::Delete from outside it deletes the object that I have created previously (ex: CThread *thread = new CThread) or deletes something internally?

Finally, I want to use the threads with GUI controls like the progress bar to increasing or decreasing its value, How can I do that?
Last edited by lionking on Mon Jan 13, 2020 7:20 am, edited 1 time in total.

alys666
Super wx Problem Solver
Super wx Problem Solver
Posts: 317
Joined: Tue Oct 18, 2016 2:31 pm

Re: The thread does not want to finish because of the “TestDestroy” always return false.

Post by alys666 » Mon Jan 13, 2020 7:19 am

if you want just test how the thread works, do your diagnostics via printf(...), or std::cout<<"text".
as doubleMax said you cannot use visual objects of wxWidgets from secondary threads, you can only send messsges of wxThreadMessage class to main frame(or any window of wxWidgets).
ubuntu 16.04, wxWidgets 3.0.4

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2235
Joined: Sun Jan 03, 2010 5:45 pm

Re: The thread does not want to finish because of the “TestDestroy” always return false.

Post by PB » Mon Jan 13, 2020 7:22 am

You can see an example how to update the UI from thread e.g. here
viewtopic.php?f=1&t=46485#p194840
alys666 wrote:
Mon Jan 13, 2020 7:19 am
if you want just test how the thread works, do your diagnostics via printf(...), or std::cout<<"text".
I would recommend using wxLog instead, e.g. wxLogDebug. This should work everywhere, including Windows.

alys666
Super wx Problem Solver
Super wx Problem Solver
Posts: 317
Joined: Tue Oct 18, 2016 2:31 pm

Re: The thread does not want to finish because of the “TestDestroy” always return false.

Post by alys666 » Mon Jan 13, 2020 7:26 am

lionking wrote:
Mon Jan 13, 2020 7:12 am
Thank you for your response.
Unfortunately, I have seen that documentation link before and still don't understand it well.
If you answer my following questions you will facilitate me to understand some things that I don't understand.

After I call wxThread::Delete from outside a runtime error occurred "Read access violation".
is that error because I use wxTHREAD_DETACHED kind but when using wxTHREAD_JOINABLE wxThread::Delete will be worked fine, right?

Also, when using wxThread::Delete from outside it deletes the object that I have created previously (ex: CThread *thread = new CThread) or deletes something internally?

Finally, I want to use the threads with GUI controls like the progress bar to increasing or decreasing its value, How can I do that?
1. to interact with GUI you must send messages to... for example.. this progress bar or any window, which can access this bar and set it's new value .
2. thread.Delete just sets internal thread's bool variable to true. and TestDestroy checks it for true value, and exits the body according to your exit from loop in the thread body. Delete does not delete the thread, thread deletes himself in finalization code, as i guess.
ubuntu 16.04, wxWidgets 3.0.4

User avatar
doublemax
Moderator
Moderator
Posts: 14621
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: The thread does not want to finish because of the “TestDestroy” always return false.

Post by doublemax » Mon Jan 13, 2020 7:38 am

After I call wxThread::Delete from outside a runtime error occurred "Read access violation".
A detached thread destroys itself when it's done. So, this error will happen when the thread is already destroyed. That's why the demo code from the page i linked uses a wxCriticalSection to protect the variable that contains the thread pointer.
Use the source, Luke!

User avatar
lionking
Earned a small fee
Earned a small fee
Posts: 17
Joined: Sun Apr 07, 2019 6:07 pm

Re: The thread does not want to finish because of the “TestDestroy” always return false.

Post by lionking » Mon Jan 13, 2020 8:25 am

I thank everyone who responded to me.
Now I have understood some things that I did not understand.

Really, the threads are not easy like I was thinking.

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 3902
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: The thread does not want to finish because of the “TestDestroy” always return false.

Post by ONEEYEMAN » Mon Jan 13, 2020 3:21 pm

Hi,
Threads are not easy, but they are easy at the same time. ;-)

Also, as I pointed out in the SO - to update progress bar you don't need a thread. Look at how it is done inside the dialogs sample.

Thank you.

User avatar
lionking
Earned a small fee
Earned a small fee
Posts: 17
Joined: Sun Apr 07, 2019 6:07 pm

Re: The thread does not want to finish because of the “TestDestroy” always return false.

Post by lionking » Mon Jan 13, 2020 11:56 pm

I want to use the threads with GUI because I have a method that does several steps and I want when it finished from each step increase the progress bar and so on until finish all the steps. the following figure explains my idea:

Image

and for that, I want to use a thread to increase the progress bar after each step.

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 3902
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: The thread does not want to finish because of the “TestDestroy” always return false.

Post by ONEEYEMAN » Tue Jan 14, 2020 1:24 am

Hi,
As I said - just look at the wxProgressDialogs.

Thank you.

Post Reply