• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

libinha

Threads Visual c++

10 mensagens neste tópico

Ola! :D

Neste momento estou a desenvolver uma interface em visual c++ para comunicar com diversos sensores. Deparei-me com um pequeno problema. Para poder receber dados de diversos sensores, eu tenho de desenvolver um programa que receba dados dos mesmos ao mesmo tempo, isto é, em paralelo. Isto é feito com Threads certo?Será que me podiam dar uma ajuda global de como isso pode ser feito?onde declarar as funcoes que quero usar?Do que encontro no google nada me clarifica muito bem.

Obrigada! :bye2:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Existe um controlo que te pode ajudar nisso, experimenta procurar informação sobre o BackgroundWorker, entretanto alguém de C++ já te deve dar mais alguma ajuda (espero eu :D)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

BackgorundWorker é uma facilidade da plataforma .net. Só se estiveres a utilizar C++/CLI é que podes utilizar isso.

Se for C++ "puro", dá um pouco mais de trabalho.

Vou dar um exemplo de um programa que cria duas threads e fica à espera que elas terminem. Atenção que este código é específico para Windows.

#include <windows.h>
#include <iostream>

const int n_threads = 2;

using namespace std;

class thParams {	/* Classe para enviar parâmetros à função da thread */
public:
const char *str;
int nr;
thParams(const char *_str, const int _nr): str(_str), nr(_nr) {}
};

DWORD WINAPI threadFunc1(LPVOID parameter) {
cout << "Sou a thread 1 e vou dormir 10 segundos!\n";
Sleep(10000);
return 0;
}

DWORD WINAPI threadFunc2(LPVOID parameter) {
thParams *parms = (thParams*)parameter;
cout << "Sou a thread 2, recebi a string \"" << parms->str << "\" e o inteiro " << parms->nr << " e vou dormir 5 segundos!\n";
Sleep(5000);
return 0;
}

int main(void) {
HANDLE threads[n_threads];

thParams *par = new thParams("Frase para escrever", 10);

/* Criar duas threads, uma com inicio na função threadFunc1, sem receber parâmetros */
threads[0] = CreateThread(NULL, 0, threadFunc1, NULL, 0, NULL);
/* e outra com a threadFunc2, que receberá como parâmetro uma classe thParams */
threads[1] = CreateThread(NULL, 0, threadFunc2, (LPVOID)par, 0, NULL);

/* Esperar que todas as threads terminem */
WaitForMultipleObjects(n_threads, threads, TRUE, INFINITE);

return 0;
}

Este código não faz qualquer verificação de erros, o que é mau.

Tens mais informação aqui, e qualquer dúvida, pergunta.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Por exemplo na minha interface. Eu tenho um botao de connect e outro de disconnect para cada sensor. Quando carrego no connect ele vai para um thread que tem as funcoes relativas à comunicacao com a serial port e fica aí até carregar no disconnect onde coloca a funcao exitthread, certo?

Depois no connect do outro sensor, ao mesmo tempo, faco exactamente o mesmo...podendo aceder às mesmas funcoes?

Nao sei o que colocar no lpParam???penso que ainda nao percebi bem o uso das threads?Alguem consegue entender qual é o meu problema?

Estou a necessitar urgentemente de ajuda neste tópico.

E já agora!será mais fácil fazer a minha GUI utilizando o Qt no C++.

Mais uma vez muito obrigada pela ajuda

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não sei se percebi bem a dúvida, mas podes utilizar a mesma função para mais que uma thread.

O lpParam serve para enviar parâmetros para as threads. No teu caso, por exemplo, se tens um botão para ligar ao COM1, e outro para o COM2, poderias fazer o seguinte:

class ComPort {
    int number;
}

HANDLE threads[10];
/* volatile para que seja sempre lido o seu valor da memória e não da cache */
volatile bool StopReadingComPort[10];

/* ... */

DWORD WINAPI thReadComPort(LPVOID cp) {
    ComPort *com_port = (ComPort)cp;

    cout << "Vou ler a porta COM numero " << com_port->number << endl;

    /* salvaguardar partilha de StopReadingComPort[com_port->number] */
    while (StopReadingComPort[com_port->number] == false) {
        /* parar salvaguarda da partilha porque a variável já foi lida */
        /* ler porta com */
        /* salvaguardar partilha de StopReadingComPort[com_port->number] para o próximo ciclo*/
    }
    /* parar salvaguarda da partilha do último ciclo */
    return 0;
}

/* ... */

void btReadCom1Pressed() { /* funcao chamada quando e pressionado o botao da COM1 */
    ComPort *com_port = new ComPort();

    com_port.number = 1;

    /* criar uma thread com a função thReadComPort e passar-lhe com_port como
       argumento de forma a que a função saiba qual a porta COM a ler */
    threads[0] = CreateThread(NULL, 0, thReadComPort, (LPVOID)com_port, 0, NULL);
}

void btReadCom2Pressed() { /* funcao chamada quando e pressionado o botao da COM2 */
    ComPort *com_port = new ComPort();

    com_port.number = 2;

    /* criar uma thread com a função thReadComPort e passar-lhe com_port como
       argumento de forma a que a função saiba qual a porta COM a ler */
    threads[1] = CreateThread(NULL, 0, thReadComPort, (LPVOID)com_port, 0, NULL);
}

void btStopCom1Pressed() { /* funcao chamada quando e pressionado o botao para parar de ler da COM1 */
    /* salvaguardar consistência de dados de StopReadingComPort[0] */
    StopReadingComPort[0] = true;
    /* parar salvaguarda da partilha porque a variável já foi escrita */
}

int main(void) {
    // (...)
    for (int i = 0; i< 10; ++i) StopReadingComPort[i] = false;
    // (...)

Utilizar múltiplas threads não é uma coisa trivial, principalmente se tiveres que partilhar dados entre elas, que é o que terás que fazer para saber se o botão para parar de ler foi pressionado na função thReadComPort. Nesse caso terias que utilizar critical sections, ou monitores, ou mutexes, ou alguma outra forma de garantir que a partilha de dados não iria constituir problema.

Não testei nenhum do código acima, e sei que isto pode parecer brutal. A verdade é que até é. Multithreading não é pêra doce, pelo menos ao início. Também ainda não sei se eventualmente melhora ::D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Obrigada, Já deu para satisfazer algumas das dúvidas que tinha. Vou tentar implementar e depois se tiver mais dúvidas venho até aqui.

Obrigada

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Tentei implementar a thread mas obtenho sempre o mesmo erro com a funcao AfxBeginThread.

Erro:

Error 70 error C3867: 'CUAV_ProjectDlg::threadReadData': function call missing argument list; use '&CUAV_ProjectDlg::threadReadData' to create a pointer to member.

A funcao readdata tem de ser definida em algum lugar especifico?

Obrigada

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Pelo que percebi do erro, faltam os argumentos na chamada à função. Isso é um projecto MFC? Podes mostrar o código onde está a dar o erro?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Sim é MFC. Eu estou a fazer tudo de novo...penso que o problema está nos parametros da funcao. Vou tentar de novo e se nao consigo mando entao o código. Que desespero!!!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora