Advice for implementing start/stop of free running process? Topic is solved

If you are using wxDev-C++ for your wxWidgets design, please ask your questions here instead of in IDE Related.
Post Reply
softport
Experienced Solver
Experienced Solver
Posts: 61
Joined: Sat Jan 28, 2012 3:55 pm
Location: Houston TX
Contact:

Advice for implementing start/stop of free running process?

Post by softport »

Hi, I couldn't get the subject description very precise.

Here's what I need to do:
When I press a wxButton, the event starts code to continuously monitor a CAN bus (or say any process). However, I would like to stop the monitoring code when the same wxButton is pressed again.

I assume that once the "start monitoring" event is triggered by the wxButton, the code in the event handler is going to ignore any more events, at least from the same source, until it completes? Is it time to start learning about threads? ... no way around it?

Apologies for not having tried anything yet, but in this case it seemed more prudent to ask for advice before starting.

Thanks!
Windows XP, wxDev-C++ 7.4.2.259, wxWidgets 2.8.12, MingW
tbreina
Moderator
Moderator
Posts: 1289
Joined: Thu Nov 25, 2004 7:38 pm
Location: Coronado, CA

Re: Advice for implementing start/stop of free running proce

Post by tbreina »

Once the loop starts, the computer will not look for other events from that process until the loop completes. To solve this, you've got to add a wxApp::Yield() inside of your loop. That will allow the loop to pause momentarily to detect and process other windows events.

Here's a similar thread from this forum:
http://forums.wxwidgets.org/viewtopic.p ... op#p136337

-Tony
Everybody's got something to hide except for me and my monkey.
softport
Experienced Solver
Experienced Solver
Posts: 61
Joined: Sat Jan 28, 2012 3:55 pm
Location: Houston TX
Contact:

Re: Advice for implementing start/stop of free running proce

Post by softport »

Thanks Tony, I've been experimenting all this time (since my last post!).

I also found another function I wanted to try, wxApp.Pending . I'm doing something wrong when calling any function of the form wxApp. I assumed that wxApp is the name of my application :

class PicCanBrdFrmApp : public wxApp
{
public:
bool OnInit();
int OnExit();
};

But if I try to use PicCanBrdFrmApp.Pending(), or PicCanBrdFrmApp.Yield() in my button event handler, I get this compiler error: 'PicCanBrdFrmApp' was not declared in this scope

What newbe error am I making? For each try, there was only the single line of code in the event handler routine.

Something interesting happened when I tried wxSafeYield. The Listen On/Off button is the one with the wxSafeYield() instruction in the event handler. Below are pics of before and after pressing the button. Almost all the other controls disappear :) . The controls reappear when I run the mouse over them. The only thing they have in common, is that both groups of controls sit on top of a wxStaticBox. At the moment I don't really care about this, I thought it might be something fun to share. I'd really like to know why I can't get the wxApp.Yield and wxApp.Pending to work.

Image

Image
Windows XP, wxDev-C++ 7.4.2.259, wxWidgets 2.8.12, MingW
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Advice for implementing start/stop of free running proce

Post by doublemax »

I don't think Pending() will help you here. The correct syntax to call Yield() is wxTheApp->Yield() or wxGetApp().Yield().

How exactly does the monitoring work? Does it have to happen in a closed loop, can't you use a timer for it?

If you're interested in receiving low level input from HID devices, this might be useful:
http://msdn.microsoft.com/en-us/library ... 85%29.aspx
Use the source, Luke!
softport
Experienced Solver
Experienced Solver
Posts: 61
Joined: Sat Jan 28, 2012 3:55 pm
Location: Houston TX
Contact:

Re: Advice for implementing start/stop of free running proce

Post by softport »

Thanks doublemax, now those instructions are not causing a compiler error anymore. I'm having the same trouble with wxApp::FilterEvent, but I think it's a matter of where this function can run (not in an event servicing routine?). I found this example on how to use Filter Event, and am about to try it gain.

In the code below I tried to use Pending from inside the loop, and it seems to work. At least it prints out "event pending" every time I do something with the mouse. Unfortunately setting the triggering button to modal does not work, you can still click and get an event from the other buttons (AND the program executes their functions). It looks promising though, because if I can filter out the event for the button that triggered the loop, then I could exit the loop.

Code: Select all

void PicCanBrdFrm::Button_Listen_CAN_Click(wxCommandEvent& event)
{
    int keepGoing = TRUE;
    wxString str;
    
    Button_Listen_CAN_->MakeModal(TRUE); //Should, but doesn't disable all other buttons

    while(keepGoing)
    {
        // --- One iteration of monitoring code here ---
        // for now just this:
        usleep(999999);    

        if(wxTheApp->Pending() == TRUE)
        {
           // Test which events are pending.
           // If event is Button_Listen_CAN_ then set keepGoing = FALSE

           // For diagnostics 
           str.Printf("events pending \n");
           WxTextCtrl_OutputWindow->AppendText(str);

           wxTheApp->Yield(TRUE); // True <=> Only if needed   
        }
    }
    
    Button_Listen_CAN_->MakeModal(FALSE);
}


The sad thing is, I don't even need a monitoring loop, it would just be a nice feature. All that's needed is to send 2047 can messages out , each time with the ID field (11 bits) incremented by 1, and listen for a response.

So yes, I could try 2 buttons: start and stop, use a yield in the monitoring loop, and be done with it. Now I know the STOP button would work, other events will be processed during the yield, so I could set a global flag to stop the loop. Or also a timer. But the one button solution is so close.

Thanks for the link on the Microsoft info. So far the hidapi library has provided all the needed usb functions. I will take a closer look at it though, just in case.
Last edited by softport on Sun Dec 23, 2012 8:01 pm, edited 1 time in total.
Windows XP, wxDev-C++ 7.4.2.259, wxWidgets 2.8.12, MingW
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Advice for implementing start/stop of free running proce

Post by doublemax »

That all sounds a little hackish. I think you should try running the HID stuff in a secondary thread, even if the communication with the GUI will be more effort that way.
Use the source, Luke!
softport
Experienced Solver
Experienced Solver
Posts: 61
Joined: Sat Jan 28, 2012 3:55 pm
Location: Houston TX
Contact:

Re: Advice for implementing start/stop of free running proce

Post by softport »

Last night I started reading about how to set up threads. That would be best, so it's time to put this button thing aside for now, and move on to do what needs to be done. Then worry about the darn button and threads.

thanks doublemax, and Tony.

Walter
Windows XP, wxDev-C++ 7.4.2.259, wxWidgets 2.8.12, MingW
softport
Experienced Solver
Experienced Solver
Posts: 61
Joined: Sat Jan 28, 2012 3:55 pm
Location: Houston TX
Contact:

Re: Advice for implementing start/stop of free running proce

Post by softport »

Hi again, today I made my first (test) program that creates a thread.

It's function:
1. Press front panel button to start the thread.
2. On entry the thread sends back an event, signalling that it has started
3. Main program sets a flag "Thread running".
4. If you press the button again, and "Thread running" flag is still set, it will not start another thread.
5. On exit, the thread sends back an event, signalling that it is stopping
6. Main program clears "Thread running" flag.

All good so far. Now I would like to make this change: if you press the button, and the thread is running, it should kill the thread. However, I get a compiler error when I use t->Delete(). I also tried MyThread->Delete(), MyThread.Delete(), t.Delete() etc. What am I doing wrong? Thanks!

t->Delete() , or t.Delete() ... 't' was not declared in this scope
MyThread->Delete() ... expected unqualified-id before '->' token
MyThread.Delete() ... expected unqualified-id before '.' token

Code: Select all

void ThreadsFrm::WxButton1Click(wxCommandEvent& event)
{
    bool bRunning;
    
    bRunning = get_ThreadRunning();
    
    if(bRunning == false)
    {    
        // create the thread
        MyThread* t = new MyThread(this);
        wxThreadError err = t->Create();
            
        if (err != wxTHREAD_NO_ERROR)
        {
            wxMessageBox( _("Couldn't create thread!") );
        }
            
        err = t->Run();
            
        if (err != wxTHREAD_NO_ERROR)
        {
            wxMessageBox( _("Couldn't run thread!") );
        }
    }
    else
    {
        t->Delete();   // This causes a compiler error
        //wxMessageBox("Thread already running");
    }
}
Windows XP, wxDev-C++ 7.4.2.259, wxWidgets 2.8.12, MingW
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Advice for implementing start/stop of free running proce

Post by doublemax »

Code: Select all

MyThread* t = new MyThread(this);
You're creating a local variable which is only visible in the scope of the if()-part. You must store it in a member variable of ThreadsFrm.
Use the source, Luke!
softport
Experienced Solver
Experienced Solver
Posts: 61
Joined: Sat Jan 28, 2012 3:55 pm
Location: Houston TX
Contact:

Re: Advice for implementing start/stop of free running proce

Post by softport »

Thanks doublemax, I was thinking about that and wondering if it would result in the thread being created (using up memory), before it's needed. But I could just move the MyThread* t = new MyThread(this) out into Frm,
and keep wxThreadError err = t->Create(); in the button event routine?
Windows XP, wxDev-C++ 7.4.2.259, wxWidgets 2.8.12, MingW
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Advice for implementing start/stop of free running proce

Post by doublemax »

But I could just move the MyThread* t = new MyThread(this) out into Frm,
and keep wxThreadError err = t->Create(); in the button event routine?
You could, but i wouldn't do it.

What i meant is to just move the pointer variable to ThreadsFrm.

So instead of:

Code: Select all

MyThread* t = new MyThread(this):
you write:

Code: Select all

// "t" must be declared as member variable of "ThreadsFrm"
t = new MyThread(this);
Use the source, Luke!
softport
Experienced Solver
Experienced Solver
Posts: 61
Joined: Sat Jan 28, 2012 3:55 pm
Location: Houston TX
Contact:

Re: Advice for implementing start/stop of free running proce

Post by softport »

That looks a lot cleaner than what I ended up with, so I'll study it and implement it if I can.

This is how I got it to work:

In "class ThreadsFrm : public wxFrame" :
made a private variable: wxThread* t;
made public function: void setT(wxThread* myThreadPointer);

In ThreadsFrm.cpp:

Code: Select all

void ThreadsFrm::setT(wxThread* myThreadPointer)
{
    t = myThreadPointer;
}
New button function calls setT function:

Code: Select all

void ThreadsFrm::WxButton1Click(wxCommandEvent& event)
{
    bool bRunning;
    
    bRunning = get_ThreadRunning();
    
    if(bRunning == false)
    {    
        // Make t point to MyThread
        setT(new MyThread(this));
        
        wxThreadError err = t->Create();
            
        if (err != wxTHREAD_NO_ERROR)
        {
            wxMessageBox( _("Couldn't create thread!") );
        }
            
        err = t->Run();
            
        if (err != wxTHREAD_NO_ERROR)
        {
            wxMessageBox( _("Couldn't run thread!") );
        }
    }
    else
    {
        t->Delete();
        //wxMessageBox("Thread already running");
    }
}


For completeness, here is where I found the information that helped me get started on threads. It starts off with
a very simple and complete example:
Inter-Thread and Inter-Process communication

Also:
Types of wxThreads, wxThread deletion, Don't poll a wxThread

Last but not least, when everything is together but something isn't quite right:
DOUBLEMAX.
Windows XP, wxDev-C++ 7.4.2.259, wxWidgets 2.8.12, MingW
Post Reply