I have a problem, I have to save into a txt file a lot of data, the problem is that I receive them every 100ns from a serial port.
How can i do? I tried to put data on a RichTextBox but I receive a thread error.
Sorry for my English.
I'm using Windows 7 64bit
private: void FindPorts(void)
{
array<Object^>^ ListaPorte = SerialPort::GetPortNames();
this->cmbPort->Items->AddRange(ListaPorte);
}
private: System::Void btnOpenPort_Click(System::Object^ sender, System::EventArgs^ e)
{
if(this->cmbPort->Text==String::Empty || this->cmbBaudRate->Text==String::Empty)
this->rtbLog->Text="cmbError";
else
{
try{
if(!this->serialPort->IsOpen)
{
this->serialPort->PortName = this->cmbPort->Text;
this->serialPort->BaudRate = Int32::Parse(this->cmbBaudRate->Text);
this->serialPort->Open();
this->rtbLog->Text+="Porta aperta\r\n";
this->btnOpenPort->Text="Close Port";
}
else
{
this->serialPort->Close();
this->rtbLog->Text+="Porta chiusa\r\n";
this->btnOpenPort->Text="Open Port";
}
}
catch(UnauthorizedAccessException^)
{
this->rtbLog->Text+="UnauthorizedAccessException\r\n";
}
}
}
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
if(!lettura)
{
lettura = true;
this->button1->Text="sto leggendo";
}
else
if(lettura)
{
lettura=false;
//rtbLog->Text += letturaBuffer;
this->button1->Text="sono ferma";
}
//serialPort->
}
private: System::Void serialPort_DataReceived(System::Object^ sender, System::IO::Ports::SerialDataReceivedEventArgs^ e)
{
if(lettura){
//letturaBuffer += serialPort->ReadExisting() + "\r\n";
rtbLog->Text += serialPort->ReadExisting() + "\r\n";
}
}
With a normal OS you wont be able to hold the pace if the data always comes at 100ns interval. 100ns interval is 10MHz so you should look for a realtime OS's that can deal with that speed. To display it in realtime you need lightweight components, so actually you should benchmark that RichTextBox and check if it can handle 10MHz.
Another problem you might have is the interrupt latency, if it takes 1us to get it, you already missed 10 data transfers.
It's unlikely you're getting data every 100 ns: The maximum speed for a standard serial port is 115,200 bits per second, which is 11,520 bytes per second, maximum. Even if your event is getting signaled for every byte received (also unlikely), that's every 87 microseconds, not every 100 nanoseconds.
The reason you're getting a thread error is because the serialPort_DataReceived method is being called on a threadpool thread, and UI components can only be accessed from the UI thread. Let's fix that, then worry about how often you want to do this, and whether it's possible in a non-RTOS.
It looks from your code like you're using WinForms, not WPF. Give this a try:
void AddAString(String^ s)
{
this->rtbLog->Text += (s + Environment::NewLine);
}
void serialPort_DataReceived(Object^ sender, SerialDataReceivedEventArgs^ e)
{
if(lettura)
{
this->BeginInvoke(
gcnew Action<String^>(this, MyClass::AddAString),
serialPort->ReadExisting());
}
}
Related
For learning purposes I made application that sends file across network (which work very well for me). Here I will post main part of code, the code that actually sends bytes, I think that is enough.
My primary question is: When, where, why and how should I check for errors? (looks like more than one question :) )
As you can see, I checked for errors by checking return values of every function that can warn me that way (I marked every check with number to make easier to those who want to help to answer and explain).
Is this necessary? Because it can expand code significantly.
Secondary question:
Is this what I made OK, is there a better way to do it?
while(!file->atEnd()){
if(isCancelled())//this is in a thread, and there is mechanism to cancel it
return;
if((readed = file->read(inter_buffer,BUFLEN)) == -1){ //1 <- marking check with "1"
emit errorOccurred(tr("Error while reading file."));
return;
}
if(socket->write(inter_buffer,readed) == -1){//2 QTcpSocket::write
emit errorOccurred(tr("Unable to send data. Probably the other side cancelled or there are connection problems."));
qDebug() << socket->error();
return;
}
rsofar += readed;
if(!socket->flush()){//3
emit errorOccurred(tr("Unable to send data. Probably the other side cancelled or there are connection problems."));
return;
}
//emit signal to inform GUI thread about progress
emit updateProgress((int)(((double)rsofar)/(double)filesize * 100.0));
if(!socket->waitForBytesWritten()){//4
//maybe this is not the right message, but that is not important now
emit errorOccurred(tr("Unable to send data. Probably the other side cancelled or there are connection problems."));
return;
}
}
Đ¢ertiary question is: In Java I would rely on Exceptions to handle this kind of problems. Why Qt functions does not throw exceptions? Is it because it is considered slow for C++ (because of stack unrolling), or just bad habit when programming in C++, or because it does not work well with signals and slots, or something else?
Exceptions can add memory and runtime overhead on some C++ implementations. It's not a problem on modern, well maintained C++ implementations - but Qt has to run and compile on some really obsolete or awkward platforms. Not only that - Qt (at least the core) has to compile and run properly with compiler's exception support disabled.
Your error code checking is almost correct. In your case, if write returns any size other than readed, it should be treated as an error. Grammar nitpick: the correct form is "read", not "readed". Yes, you have "written" but simply "read". English is weird like that ;)
There is no need to use flush(). Just waitForBytesWritten and then check how many bytes still remain to be written and report progress based on that. You're making things run slower since your approach can't amortize the latency of disk file access: you don't do network sending and file reading in parallel.
So, what you're doing is somewhat convoluted. You don't need to use blocking waitForX functions at all. You're running in a thread, so let's just use signals provided by QIODevice and use the default event loop that QThread's run() method is spinning. That way you can process multiple files in the same worker thread. Your implementation requires a dedicated thread for each file processed in parallel.
The code below should work. Simply use moveToThread to move it to a worker QThread - don't derive from QThread. To start sending, invoke the start() slot. To cancel sending, all you need to do is to call sender->deleteLater().
#include <QTcpSocket>
#include <QByteArray>
class Sender : public QObject {
Q_OBJECT
QIODevice * m_src;
QAbstractSocket * m_dst;
QByteArray m_buf;
qint64 m_hasRead;
qint64 m_hasWritten;
qint64 m_srcSize;
bool m_doneSignaled;
bool signalDone() {
if (!m_doneSignaled &&
((m_srcSize && m_hasWritten == m_srcSize) || m_src->atEnd())) {
emit done();
m_doneSignaled = true;
}
return m_doneSignaled;
}
Q_SLOT void dstBytesWritten(qint64 len) {
if (m_dst->bytesToWrite() < m_buf.size() / 2) {
// the transmit buffer is running low, refill
send();
}
m_hasWritten += len;
emit progressed((m_hasWritten * 100) / m_srcSize);
signalDone();
}
Q_SLOT void dstError() {
emit errorOccurred(tr("Unable to send data. Probably the other side"
"cancelled or there are connection problems."));
qDebug() << m_dst->error();
}
void send() {
if (signalDone()) return;
qint64 read = m_src->read(m_buf.data(), m_buf.size());
if (read == -1) {
emit errorOccurred(tr("Error while reading file."));
return;
}
m_hasRead += read;
qint64 written = m_dst->write(m_buf.constData(), read);
if (written == -1) {
emit errorOccurred(tr("Unable to send data. Probably the other side "
"cancelled or there are connection problems."));
qDebug() << m_dst->error();
return;
}
if (written != read) {
emit errorOccurred(tr("Internal error while filling write buffer."));
qDebug() << m_dst->error();
return;
}
}
public:
/*! Requires a source device open for reading, and a destination socket open
for writing. */
Sender(QIODevice * src, QAbstractSocket * dst, QObject * parent = 0) :
QObject(parent), m_src(src), m_dst(dst), m_buf(8192, Qt::Uninitialized),
m_hasRead(0), m_hasWritten(0), m_doneSignaled(false)
{
Q_ASSERT(m_src->isReadable());
Q_ASSERT(m_dst->isWritable());
connect(m_dst, SIGNAL(bytesWritten(qint64)), SLOT(dstBytesWritten(qint64)));
connect(m_dst, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(dstError()));
m_srcSize = m_src->size();
}
Q_SLOT void start() { send(); }
Q_SIGNAL void done();
Q_SIGNAL void errorOccurred(const QString &);
Q_SIGNAL void progressed(int percent);
};
I've wrote a timer using std::thread - here is how it looks like:
TestbedTimer::TestbedTimer(char type, void* contextObject) :
Timer(type, contextObject) {
this->active = false;
}
TestbedTimer::~TestbedTimer(){
if (this->active) {
this->active = false;
if(this->timer->joinable()){
try {
this->timer->join();
} catch (const std::system_error& e) {
std::cout << "Caught system_error with code " << e.code() <<
" meaning " << e.what() << '\n';
}
}
if(timer != nullptr) {
delete timer;
}
}
}
void TestbedTimer::run(unsigned long timeoutInMicroSeconds){
this->active = true;
timer = new std::thread(&TestbedTimer::sleep, this, timeoutInMicroSeconds);
}
void TestbedTimer::sleep(unsigned long timeoutInMicroSeconds){
unsigned long interval = 500000;
if(timeoutInMicroSeconds < interval){
interval = timeoutInMicroSeconds;
}
while((timeoutInMicroSeconds > 0) && (active == true)){
if (active) {
timeoutInMicroSeconds -= interval;
/// set the sleep time
std::chrono::microseconds duration(interval);
/// set thread to sleep
std::this_thread::sleep_for(duration);
}
}
if (active) {
this->notifyAllListeners();
}
}
void TestbedTimer::interrupt(){
this->active = false;
}
I'm not really happy with that kind of implementation since I let the timer sleep for a short interval and check if the active flag has changed (but I don't know a better solution since you can't interrupt a sleep_for call). However, my program core dumps with the following message:
thread is joinable
Caught system_error with code generic:35 meaning Resource deadlock avoided
thread has rejoined main scope
terminate called without an active exception
Aborted (core dumped)
I've looked up this error and as seems that I have a thread which waits for another thread (the reason for the resource deadlock). However, I want to find out where exactly this happens. I'm using a C library (which uses pthreads) in my C++ code which provides among other features an option to run as a daemon and I'm afraid that this interfers with my std::thread code. What's the best way to debug this?
I've tried to use helgrind, but this hasn't helped very much (it doesn't find any error).
TIA
** EDIT: The code above is actually not exemplary code, but I code I've written for a routing daemon. The routing algorithm is a reactive meaning it starts a route discovery only if it has no routes to a desired destination and does not try to build up a routing table for every host in its network. Every time a route discovery is triggered a timer is started. If the timer expires the daemon is notified and the packet is dropped. Basically, it looks like that:
void Client::startNewRouteDiscovery(Packet* packet) {
AddressPtr destination = packet->getDestination();
...
startRouteDiscoveryTimer(packet);
...
}
void Client::startRouteDiscoveryTimer(const Packet* packet) {
RouteDiscoveryInfo* discoveryInfo = new RouteDiscoveryInfo(packet);
/// create a new timer of a certain type
Timer* timer = getNewTimer(TimerType::ROUTE_DISCOVERY_TIMER, discoveryInfo);
/// pass that class as callback object which is notified if the timer expires (class implements a interface for that)
timer->addTimeoutListener(this);
/// start the timer
timer->run(routeDiscoveryTimeoutInMilliSeconds * 1000);
AddressPtr destination = packet->getDestination();
runningRouteDiscoveries[destination] = timer;
}
If the timer has expired the following method is called.
void Client::timerHasExpired(Timer* responsibleTimer) {
char timerType = responsibleTimer->getType();
switch (timerType) {
...
case TimerType::ROUTE_DISCOVERY_TIMER:
handleExpiredRouteDiscoveryTimer(responsibleTimer);
return;
....
default:
// if this happens its a bug in our code
logError("Could not identify expired timer");
delete responsibleTimer;
}
}
I hope that helps to get a better understanding of what I'm doing. However, I did not to intend to bloat the question with that additional code.
I like to use the Sleep() function in a Windows Forms project, but the Sleep() is executed before anything else. I read that i should flush using fflush(), but i don't know what to flush. Can someone help me?
The code:
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
this->label1->Visible= false;
this->button1->Visible= false;
r = (float)rand()/(float)RAND_MAX;
r = r*100000;
i = r;
r = r - i;
String^ strR = "" + r;
this->label2->Text = strR;
if(r >= 0.5)
{
this->pictureBox1->Visible= true;
this->pictureBox1->BackColor = System::Drawing::Color::Blue;
}
else
{
this->pictureBox1->Visible= true;
this->pictureBox1->BackColor = System::Drawing::Color::Red;
}
Sleep(500);
}
The call to Sleep() is blocking your main (UI) thread, which prevents the message pump from updating your controls.
In this case, it doesn't appear that the call to Sleep really serves a purpose, other than blocking your UI - if you want to prevent the button from being pressed again, a better option would be to disable it, then use a timer (System::Windows::Forms::Timer) with a 500 ms interval to re-enable the button.
By using a timer, you won't block the UI thread, which allows your controls to stay active, but you still prevent the user from pressing the button.
This is a Visual Studio Express C++ Windows Forms application.
I want to play a WAV file strFileName.WAV in a WAV play wavPlayer every 10 seconds from the time I press the "Start" button until such time as I press the "Stop" button.
When each 10 second interval is up, TimerEventProcessor plays the WAV file.
The problem is that I have to press "Stop" twice to get it to work. The first press of "Stop" seems to be ignored.
Why is btnStop_Click not executing the first time I press "Stop"?
private: System::Void bntStart_Click(System::Object^ sender, System::EventArgs^ e) {
if (String::IsNullOrEmpty(strFileName)) {
lblRunning->Text = L"Cannot Start Until File Is Loaded";
}
else {
lblRunning->Text = L"Running";
myTimer->Interval = iIntervalSeconds * 1000;
myTimer->Tick += gcnew EventHandler( TimerEventProcessor );
myTimer->Enabled = true;
while (lblRunning->Text == L"Running") {
Application::DoEvents();
}
}
}
private: System::Void btnStop_Click(System::Object^ sender, System::EventArgs^ e) {
lblRunning->Text = L"Stopped";
myTimer->Enabled = false;
wavPlayer->Stop();
}
Get rid of the
while (lblRunning->Text == L"Running") {
Application::DoEvents();
}
loop. When you return from bntStart_Click the form will return to dispatching messages and the timer will tick as expected. There is no need for you to create a manual Application::DoEvents() loop, which is probably the cause of your problem.
By calling Application::DoEvents(); in a loop you are creating a pooling loop for window messages. Without any sleep call this loop cause 100% CPU usage. By letting your bntStart_Click return the WinForms runtime will sleep your process until a message is ready - resulting in very low CPU usage.
This high CPU usage is probably making your application unresponsive which is why it seems that clicks are not being processed.
The following function is created in a boost thread. In a console app it works like this.
void function()
{
/* snip */
try
{
/* Do stuff, in this case a P2P transfer is started using an external library
as long as this thread is active, the P2P transfer will be too. */
//Prevent thread from closing
char a;
std::cin >> a;
}
catch (std::exception& e)
{
/* snip */
}
return 0;
}
Which would prevent the thread from being closed until a user types something. Ultimately, what I want is this:
void function()
{
int x = 1;
/* snip */
try
{
/* Do stuff, in this case a P2P transfer is started using an external library
as long as this thread is active, the P2P transfer will be too. */
//Prevent thread from closing
while(x = 1)
{
//Do nothing until the user stops the transfer (x becomes 0 when the user hits stop)
}
}
catch (std::exception& e)
{
/* snip */
}
return 0;
}
But this is no good.. the CPU spikes to 100%. I tried putting sleep(1); in the while loop, but it made no difference and I'm not sure how that would affect the transfer.