Jump to content
Sign in to follow this  
eskalha

Problema de cross-thread

Recommended Posts

eskalha

Boa noite.

Estou com um pequeno (ou grande nem sei) problema.

A minha aplicação conecta com um aparelho o clique de um botão, que chama um método Connect() com o seguinte código:

public bool Connect()
        {
            
            
            bool con = false;            
            try
            {
                
            // Se a porta ja está aberta, fecha
                if (this.serialPort1.IsOpen)
                {
                    this.serialPort1.Close();
                    btnConn.Text = "Conectar";
                }
                else
                {
                    // configurações da porta

                    this.serialPort1.BaudRate = baudRate;
                    this.serialPort1.DataBits = bitsDados;
                    this.serialPort1.StopBits = stopBits;
                    this.serialPort1.Parity = paridade;
                    this.serialPort1.PortName = portName;
                    this.serialPort1.Handshake = flowCtrl;
                    //this.serialPort1.PortName = "COM3";

                    // abre a porta
                    serialPort1.Open();
                    serialPort1.DtrEnable = true;
                    serialPort1.RtsEnable = true;
                    serialPort1.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
                    this.Invoke(new SerialDataReceivedEventHandler(port_DataReceived));

                    con = true;
                    return con;
.....

Aqui tudo tranquilo, conecta.

Mas depois tenho que comunicar com esse aparelho, enviando-lhe comandos, e ao clicar no botao de enviar é chamado o método EnviarDados(string texto):

private void EnviarDados(string msg)
        {
            //if (CurrentDataMode == DataMode.Text)
            //{
            // Envia texto para a porta
            if (serialPort1.IsOpen)
            {
                serialPort1.WriteLine(msg);


                // Mostra no terminal o texto do user
                rtbEnviar.Text += msg + "\n";
            }
.......

Depois, como é enviado o comando para o aparelho, estas linhas de codigo:

serialPort1.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
                    this.Invoke(new SerialDataReceivedEventHandler(port_DataReceived));

Despoletam a chamada ao método port_DataReceived:

 private void port_DataReceived(object sender, EventArgs e)
        { // este método irá ser chamado quando existirem dados no buffer da porta
           
            Thread.Sleep(1);
            
            // se a porta for fechada, nao faz nada
            if (serialPort1.IsOpen)
            {
               

                // le todos os dados à espera no buffer
                //int data = serialPort1.ReadByte();
                string data = serialPort1.ReadExisting();


                // mostra no terminal 
                rtbEnviar.Text += data + "\n";
...............

O meu problema é o seguinte: eu, ao enviar um comando, inserido numa textBoxt, para o aparelho, esse mesmo comando é escrito numa rich TextBox (rtbEnviar). Até aqui tudo bem, mas ao ser executado o método port_DataReceived da um erro de cross-thread na linha  "rtbEnviar.Text += data + "\n"";. Diz que a rtbEnviar não pode ser acedida por uma thread além daquela pela qual foi criada.

Como resolvo este problema?

Se precisarem de mais esclarecimentos é só dizer.

Desde já obrigado

Share this post


Link to post
Share on other sites
softklin

Esse erro acontece porque estás a tentar escrever numa textbox que está a correr noutra thread. Vê este artigo do MSDN, explica o erro e dá um exemplo de como resolver:

http://msdn.microsoft.com/en-us/library/ms171728%28v=vs.80%29.aspx

Em alternativa, acho que se usares backgroundworkers, não te deparas com este problema.


Nick antigo: softclean | Tens um projeto? | Wiki P@P

Ajuda a comunidade! Se encontrares algo de errado, usa a opção "Denunciar" por baixo de cada post.

Share this post


Link to post
Share on other sites
eskalha

Podias me dar um exemplo de como se usa backgroundworkers? é que disso não percebo mesmo nada.

Tive a ver noutros foruns e aconselharam criar um private delegate void teste() e depois fazer a chamada

this.Invoke(new teste(port_DataReceived))

Mas dá erro, provavelmente por o método port_DataReceived receber dois parâmetros (object sender, EventArgs e) mas não percebo nada :S

Share this post


Link to post
Share on other sites
Gonka
BackgroundWorker worker = new BackgroundWorker();

worker.DoWork += (sender, e) =>
{
     //TODO
}
worker.RunWorkerCompleted += (sender, e) =>
{
    //TODO
}
worker.RunWorkerAsync();

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.