Thread and GUI

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.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Thread and GUI

Post by doublemax »

ONEEYEMAN wrote: Thu Mar 18, 2021 5:44 am wxQueueEvent ques an event for later processing and therefore does not return any values.

So how do I check if the event is processed?

What do I modify in my pseudo-code?
For this i would add another method to DBResultConsumerInterface, e.g. bool ReadyToProcess() which the thread uses to check if the main thread is ready to process data. If it's not, just let the thread sleep a little bit.
You just need a busy flag in the processing code that the thread can check.
Use the source, Luke!
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7459
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Thread and GUI

Post by ONEEYEMAN »

double max,
You mean poll inside the thread?

If not - then how?

Thank you.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Thread and GUI

Post by doublemax »

ONEEYEMAN wrote: Thu Mar 18, 2021 12:18 pm double max,
You mean poll inside the thread?
Yes
Use the source, Luke!
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7459
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Thread and GUI

Post by ONEEYEMAN »

doublemax,
Can I directly reset the flag from a thread or I will need an event for that?
If its the latter - is there a guarantee that the event processing will done properly?

Thank you.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Thread and GUI

Post by doublemax »

ONEEYEMAN wrote: Thu Mar 18, 2021 2:03 pm Can I directly reset the flag from a thread or I will need an event for that?
The processing code (in the main thread) is responsible for setting and resetting it.
Use the source, Luke!
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7459
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Thread and GUI

Post by ONEEYEMAN »

doublemax,
So it will go like this (IIUC):

In the main thread:

Code: Select all

wxView::wxView()
[
    dataProcessed = false;
}

void OnThreadEvent(wxThreadEvent &event)
{
    // process the row
    dataProcessed = true;
}
In the thread:

Code: Select all

Entry()
{
    int res = GetRecord();
    if( !res ) // success
    {
        wxThreadEvent event( wxEVT_THREAD, WORKING_DATA );
        event.SetPayload( row );
        wxQueueEvent( m_view, event.Clone() );
        while( !m_view->GetDataProcessed )
            wxSleep( 500 );
        m_view->ResetDataProcessed(); // set the flag to false;
    }
}
Am I missing something?

Thank you.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Thread and GUI

Post by doublemax »

This is now completely different from the code i suggested.

And it doesn't make any sense, the processing code needs to control the busy flag, it's the only one who has that information.
Use the source, Luke!
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7459
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Thread and GUI

Post by ONEEYEMAN »

doublemax,
Yes, it is a little different.

Your code is using the simplest case.

As I said before - let's assume I have a following table:

CREATE TABLE photos(id INTEGER PRIMARY KEY, photo BLOB);

and I store some photos in that table like 500jpg or png or bmp or whatever other graphic format files. Or maybe even more than 500 files.

When I load them in the vector all at once I will use a lot of memory.

So I'm trying to read a record from the table and then process it, clean the vector and then read another record.

So yes - it is a little different from what your suggested.

Point is - I don't know what info is stored in the DB and how much. It may be 1 simple record or it may be millions of records of the graphical data.

So - will your code work successfully in both cases? Can I read millions of records of lets say some photoalbum with your code?

Or maybe I am trying to overoptimize all this?

Thank you.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Thread and GUI

Post by doublemax »

So - will your code work successfully in both cases? Can I read millions of records of lets say some photoalbum with your code?
The "unique" part of my code was the use of a clearly defined interface to communicate between worker and main thread, and the use of CallAfter. How much data you put into the payload is independent from that and can be adjusted to match your usecase.

For a complete optimization, i'd need to know more. E.g. what do you do with the images in the main thread? If you have to rescale them, or use any kind of image processing, this is of course something that should be done in the worker thread (or even multiple worker threads) and not in the main thread.
Use the source, Luke!
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7459
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Thread and GUI

Post by ONEEYEMAN »

doublemax,
I will try to check your code again. If I have more question - I will ask.

Thank you.
sparhawk
Experienced Solver
Experienced Solver
Posts: 81
Joined: Tue May 21, 2013 8:08 am

Re: Thread and GUI

Post by sparhawk »

What you might use here is an Observer Pattern. In java this is a typical method to abstract different GUI elements from each other, so that they are independent of each other but still can communicate via events. Don't know if wxWidgets provides such a mechanism, because AFAIK normally you have to have a window for event processing. Maybe doublemax knows better.

However I have a class written which is open source, which is designed for this kind of thing and in fact I was also using it for a database program among other things. :)
If you want to take a look at it, you can find it here: https://github.com/skeetor/WinUAE/blob/ ... observer.h

Basically it works like this:

Your database reader is a Dispatcher, your GUI window is a Listener. You pass a pointer of the DB reader to the GUI which shouldn't be a problem because the GUI is allowed to know about about the DB reader. The GUI registers itself as a Listener and implements the handleNotification() function. Whenever the DB updates whatever is you want to signal, then you call notify() and all listeners will get an appropriate event. Since this is a variadic template class, you can pass any kind of parameters you need. You can register as many listeners as you like, i.E. your statusbar could be one listener which just updates the number of records, while you have a grid which shows the records in the GUI. None of them need to poll, because they will get an event when you have one.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7459
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Thread and GUI

Post by ONEEYEMAN »

doublemax,
I tried to implement the solution you gave.
Unfortunately, I'm getting an error trying to use wxTheApp or wxGetApp().

If you can get my latest sources and look at dbtableedit.cpp. The code I tried to put is:

Code: Select all

                    m_retriever->SetProcessed( true );
                    while( m_retriever->GetProcessed() )
                        wxSleep( 2 );
                    DataRetriever *retriever = m_retriever;
                    wxTheApp->CallAfter( [row, retriever]
                    {
                        retriever->DisplayData( row );
                    } );
I will push the code with the offending line commented out.

Thank you.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Thread and GUI

Post by doublemax »

ONEEYEMAN wrote: Mon Mar 29, 2021 5:56 am Unfortunately, I'm getting an error trying to use wxTheApp or wxGetApp().
Which error? As it always takes a long time getting the project to build for me, i can't test this easily.
Use the source, Luke!
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7459
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Thread and GUI

Post by ONEEYEMAN »

doublemax,
Error is "Undeclared identifier".

Hopefully you will be able to figure it out by the code (without building).

Thank you.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Thread and GUI

Post by doublemax »

wxTheApp is a global variable, it should be accessible from anywhere. Try including "wx/wx.h".
Use the source, Luke!
Post Reply