thread루틴에서 변수값 읽어오기...

cdcmp의 이미지

안녕하세요....

thread에 대한 질문을 많이 올리는데요....

thread루프에서 배열에 저장된 값을 메인 루프에서 읽어 오니까 어느 정도

읽다가 프로그램이 종료 되어 버립니다....

소스는 다음과 같습니다...


/////thread.cpp///////
#include <iostream>
using namespace std;

#include "thread.h"

FILE *fp1;

extern unsigned char buf[100000];
int cnt = 0;
int i = 0;


Thread::Thread()
{
    stopped = false;
}

void Thread::setMessage(const QString &message)
{
    messageStr = message;
}

void Thread::run()
{
    while (1)
    {
	buf[cnt] = i;
	
       fp1 =fopen("/home/eunsu/serial/sensor/thread1/data1.txt","a+");
	
	fprintf(fp1,"%d \n",buf[cnt]);
	fclose(fp1);
	i++;

	cnt++;   
    }
}

void Thread::stop()
{
    stopped = true;
}

///////threadform.cpp//////
#include <qlayout.h>
#include <qpushbutton.h>
#include <qgrid.h>

#include "thread.h"
#include "threadform.h"
int cnt1 = 0;
unsigned char buf[100000];

FILE *fp;


ThreadForm::ThreadForm(QWidget *parent, const char *name)
    : QDialog(parent, name)
{
    setCaption(tr("Threads"));

    threadA.setMessage("A");
    threadB.setMessage("B");

    threadAButton = new QPushButton(tr("Start A"), this);
    threadBButton = new QPushButton(tr("Start B"), this);
    quitButton = new QPushButton(tr("Quit"), this);
    quitButton->setDefault(true);

    connect(threadAButton, SIGNAL(clicked()),
            this, SLOT(startOrStopThreadA()));
    connect(threadBButton, SIGNAL(clicked()),
            this, SLOT(startOrStopThreadB()));
    connect(quitButton, SIGNAL(clicked()),
            this, SLOT(close()));

    QHBoxLayout *mainLayout = new QHBoxLayout(this);
    mainLayout->setResizeMode(QLayout::Fixed);
    mainLayout->setMargin(11);
    mainLayout->setSpacing(6);
    mainLayout->addWidget(threadAButton);
    mainLayout->addWidget(threadBButton);
    mainLayout->addWidget(quitButton);
}

void ThreadForm::startOrStopThreadA()
{
    if (threadA.running()) {
        threadA.stop();
        threadAButton->setText(tr("Start A"));
    } else {
        threadA.start();
        Timer1();	
        threadAButton->setText(tr("Stop A"));
    }
}

void ThreadForm::Timer1()
{
    Timer = startTimer(1);
}

void ThreadForm::timerEvent( QTimerEvent *e )
{
    if(e->timerId() == Timer)
    {
	fp = fopen("/home/eunsu/serial/sensor/thread1/data.txt","a+");
	
	fprintf(fp,"%d \n",buf[cnt1]);
	fclose(fp);
	cnt1++;
    }
}

void ThreadForm::closeEvent(QCloseEvent *event)
{
    threadA.stop();
    threadB.stop();
    threadA.wait();
    threadB.wait();
    event->accept();
}

thread 루프에서는 변수 i가 계속 증가하고 증가된 i 값을 배열 buf에

저장을 합니다...

그리고 메인 루프 threadform.cpp에서는 읽어온 배열 buf에 저장된 값을

파일로 저장을 합니다...

그런데 저장된 값들을 보면 0~255까지 저장 되고 다시 0~255까지 저장되어

있더라고요...0에서부터 계속 증가 해야 하는데....

그리고 thread가 계속 돌면서 얼마후 프로그램이 종료 되어 버리는 현상까지

생기고요...

배열 길이를 정의 하는데서 문제가 있는지....

그래서 루프를 돌리다가 중간에 어느 한 선에서 배열 카운트를 다시 0으로

초기화 시키게 됩니다...

그런데 똑같은 현상이...

고수님들 답변 부탁드리겠습니다...^^

File attachments: 
첨부파일 크기
Binary Data qextserialport.tar.gz48.98 KB
익명 사용자의 이미지

QCustomEvent를 이용하는 것은 어떨까요?
굳이 배열로 잡지 않아도 될 것 같은데요.
파일여는 루틴은 while(1) 문 바깥에 나와야 하지 않을까요?
여러개의 쓰레드를 구동하신다면 mutex나 다른 것으 이용하여
lock을 걸어주셔야지 데이터의 안전성이 보장됩니다.

다음은 제가 허접하게 서버 /클라이언트 모델 테스트하거라 만듭겁니다.
허접의 극치임을 알아두시길...

#ifndef CONNECTIONTHREAD_H
#define CONNECTIONTHREAD_H
#pragma pack(2)

#include <qthread.h>
#include <qvariant.h>

class   QWidget;
class   QMutex;
class   QSocketDevice;
class   QString;

typedef struct _packet {
    int socket_id;
    QString name;
    int age;
    QString job;
    QString phone;
}Packet;

class ConnectionThread : public QThread
{
//    Q_OBJECT

public:
        ConnectionThread(int sock, QWidget *target);
        virtual ~ConnectionThread();

        void run();
        void stop();

protected:


private:
        void readClient();
        void sendClient(const QString &str);
        void sendClient(Packet *);
        
        QWidget *receiver;
        QMutex mutex;
        QSocketDevice *socket;
        bool stopped;
        Packet packet;

};

#pragma pack()

#endif //CONNECTIONTHREAD_H

#include "connectionthread.h"
#include <qmutex.h>
#include <qsocketdevice.h>
#include <qevent.h>
#include <qapplication.h>
#include <qdatastream.h>


ConnectionThread::ConnectionThread(int sock, QWidget *target)
    : receiver(target), stopped(FALSE)
{
    socket = new QSocketDevice(sock,QSocketDevice::Stream);
    socket->setBlocking(TRUE);
    socket->setAddressReusable(TRUE);
    
    packet.socket_id=-1;
    packet.name=" ";
    packet.age=0;
    packet.job=" ";
    packet.phone=" ";

}

ConnectionThread::~ConnectionThread()
{

}

void ConnectionThread::run()
{
    for( ; ; )
    {
        if (stopped) 
        {
            mutex.lock();
            stopped = FALSE;
            mutex.unlock();
            break;
        }

        mutex.unlock();

        if( socket->isValid() )
        {
            if ( socket->bytesAvailable() ) 
            {

#ifdef  DEBUG
                qWarning("Read the client message");
#endif
                readClient();
            }
            else
            {
#ifdef  DEBUG
                qWarning("No available bytes");
#endif
                socket->waitForMore(200);
            }
        }
        else
            return ;
    }
}

void ConnectionThread::stop()
{
    mutex.lock();
    stopped = TRUE;
    mutex.unlock();
}

void ConnectionThread::readClient()
{
    QByteArray datagram(socket->bytesAvailable());
    socket->readBlock(datagram.data(),datagram.size());

    QDataStream in(datagram,IO_ReadOnly);
    in.setVersion(5);
    
    packet.socket_id = socket->socket();

    in >> packet.name >> packet.age >> packet.job >> packet.phone ;
    
    QCustomEvent *event = new QCustomEvent(12345);
    event->setData(&packet);
    QApplication::postEvent(receiver, event);
    
    sendClient(&packet); 

 }

void ConnectionThread::sendClient(const QString &str)
{
	QByteArray ba;
	QTextOStream out(ba);
	out << str;

	int wrote = socket->writeBlock( ba.data(), ba.size() );

	while( wrote < (int)ba.size() )
		wrote += socket->writeBlock( ba.data() + wrote, ba.size() - wrote);
    
    QCustomEvent *event = new QCustomEvent(12346);
    event->setData(new QString("Write Cient"));
    QApplication::postEvent(receiver,event);
}

void ConnectionThread::sendClient(Packet *pack)
{
    QByteArray datagram;
    QDataStream out(datagram,IO_WriteOnly);
    out.setVersion(5);


    out << pack->name << pack->age << pack->job << pack->phone;
    
    pack->socket_id = socket->socket();

    socket->writeBlock(datagram, datagram.size());
    

    QCustomEvent *event1 = new QCustomEvent(12347);
    event1->setData(new QString("Write to the client"));
    QApplication::postEvent(receiver, event1);
    
    QCustomEvent *event = new QCustomEvent(12346);
    event->setData(pack);
    QApplication::postEvent(receiver, event);

}
 


/****************************************************************************
** ui.h extension file, included from the uic-generated form implementation.
**
** If you want to add, delete, or rename functions or slots, use
** Qt Designer to update this file, preserving your code.
**
** You should not define a constructor or destructor in this file.
** Instead, write your code in functions called init() and destroy().
** These will automatically be called by the form's constructor and
** destructor.
*****************************************************************************/
#include "connectionthread.h"

void Server::init()
{ 
    server = new Ssocket(4242,50,this,NULL,this);
    listView->addColumn("Socket id");
    listView->addColumn("Name");
    listView->addColumn("Age");
    listView->addColumn("Job");
    listView->addColumn("Phone");
    listView->clear();

}


void Server::customEvent( QCustomEvent *event )
{
    switch( event->type() )
    {
    case 12345:
	{
	    Packet *p = (Packet *) event->data();
	    
	    QString *s = new QString( tr("Read from Client :: name=" + p->name +" age=%1 "+" job=" + p->job + " phone="+p->phone+" id : %2").arg(p->age).arg(p->socket_id)); 
	    textEdit->append(*s);
	    new QListViewItem(listView,tr("%1").arg(p->socket_id), p->name,tr( "%2").arg(p->age), p->job, p->phone);
	    delete s;
	    break;
	}
    case 12346:
	{
	    Packet *p = (Packet *) event->data();
    
	    QString *s = new QString( tr("Write to Client :: name=" + p->name +" age=%1 "+" job=" + p->job + " phone="+p->phone+" id : %2").arg(p->age).arg(p->socket_id)); 
	    textEdit->append(*s);	    
	    delete s;
	    break;
	}
    case 12347:
	{
	    QString *s = (QString *)event->data();
	    textEdit->append(*s);
	    delete s;
	    break;
	}
    default:
	qWarning("Unknown custom event type");
    }   
}
익명 사용자의 이미지

시리얼통신을 하신다면 아래 라이버리를 이용하는 것도 괜찮을 껍니다.

약간 수정하시면 괜찮게 사용하실 수 있을겁니다....

댓글 첨부 파일: 
첨부파일 크기
Binary Data 0바이트
cdcmp의 이미지

답변 감사드립니다...

위에서 제시한 방법들로 해 봐야 될거 같네요...^^

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.