Advice for implementing start/stop of free running process? Topic is solved
-
- 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?
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!
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
Re: Advice for implementing start/stop of free running proce
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
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.
-
- 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
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.
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.
Windows XP, wxDev-C++ 7.4.2.259, wxWidgets 2.8.12, MingW
Re: Advice for implementing start/stop of free running proce
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
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!
-
- 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
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.
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.
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
Re: Advice for implementing start/stop of free running proce
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!
-
- 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
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
thanks doublemax, and Tony.
Walter
Windows XP, wxDev-C++ 7.4.2.259, wxWidgets 2.8.12, MingW
-
- 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
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
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
Re: Advice for implementing start/stop of free running proce
Code: Select all
MyThread* t = new MyThread(this);
Use the source, Luke!
-
- 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
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?
and keep wxThreadError err = t->Create(); in the button event routine?
Windows XP, wxDev-C++ 7.4.2.259, wxWidgets 2.8.12, MingW
Re: Advice for implementing start/stop of free running proce
You could, but i wouldn't do it.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?
What i meant is to just move the pointer variable to ThreadsFrm.
So instead of:
Code: Select all
MyThread* t = new MyThread(this):
Code: Select all
// "t" must be declared as member variable of "ThreadsFrm"
t = new MyThread(this);
Use the source, Luke!
-
- 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
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:
New button function calls setT function:
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.
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;
}
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