Con vuestro permiso y para no perder costumbre os invito a leer este relato corto en tono de humor… que lo disfrutéis!
Hace algunos días, en una de esas reuniones de profesionales, en las que aprovechando el buen recaudo de una cena, se discuten y se tratan todo tipo de temas sin orden ni concierto; recuerdo como entre medio de disertaciones sobre metodologías, lenguajes y sintaxis, me encontré “para variar” evocando aquellos tiempos en que el pan era pan, el vino, vino y los lenguajes eran lenguajes de ¡alto nivel!.
A lo ancho de la alargada mesa se mantenían diversos “hilos” activos con diversas conversaciones “a saber cual la mejor”. Mientras sin saber porque, y acaloradamente empecé a recordar aquellos tiempos en los que los compiladores eras verdaderas joyas de la ingeniería. Aquellos tiempos en los que sin existir la programación orientada a objeto éramos capaces de depurar los ensamblados de los Intel 8086 de las lanzaderas espaciales “online” y en tiempo real, para terminar llevando a un puñado de astronautas a la luna… de pronto me grite para mis adentros :
“Pep!!! Eres un viejo incorregible, siempre terminas hablando de cómo era, pareces un petrificado historiador de informática”
A caldo de la conversación y después de mi pausa se fueron apagando el resto de conversaciones. Sin darme cuenta concentre todas las miradas mientras argumentaba que a pesar de entender la incorporación de ciertas metodologías tales como el procedimiento de realizar un “Invoke” para poder manejar datos entre hilos, tenía cierta sensación de que la medida que avanzábamos en las técnicas perdíamos ciertas purezas del lenguaje. Para poner un ejemplo, desde cierto punto de vista aunque no global, podría entender que fuera el propio compilador que decidiera como cruzar esos datos que se generan entre hilos de ejecución diferentes, de forma que no me obligara a invocar un procedimiento a no ser que yo lo explicitara.
Me gustaría poder enseñaros una foto del las caras que reflejaban los que estaban atentos a mi conversación, en ese momento no se si ponían cara de bobo por absortos o porque realmente estaban pensando que Pep estaba más loco que una cabra. Una vez mas para mis adentros pensé ..
“quien me mandara a mi meterme en semejantes pasteles! … luego me quejo de mi fama! J”.
En honor a todos los presentes y en pro de mi integridad y dedicado a mis contertulios más próximos Vicenc Masanas y Marc Rubiño, os dejo el apunte que en una línea resume lo estaba intentando explicar y que ¡en una línea! Explica que mis pensamientos no eran tan salidos de contexto ni estaban en absoluto equivocados.
CheckForIllegalCrossThreadCalls = false;
Para los que no estuvisteis en la cena… con este pragma instruimos al compilador si queremos controlar o no, las llamadas entre hilos a pesar de que sean “ilegales”, por lo tanto mi código podrá intercambiar datos entre hilos por contrabando sin necesidad de invoKar a nadie.Eso si en C++… ahora os dejo a vosotros que averigüéis si mi critica a los compiladores de C# o Visual Basic , eran infundadas y disponen de algo parecido.Cuidaros mucho y buen FinDe,
Pep Lluis,
Algunos de vosotros en el foro estáis solicitando si es posible utilizar el System.IO.Ports con C++, esperando que esto sea un punto de entrada en un ejemplo súper simple!! De solo enviar y recibir una trama.

Podéis descargaros el archivo adjunto, no esta probado en C++ express, pero supongo que no tendréis ningún problema en ejecutarlo.
Por cierto si reubicáis el proyecto (lo colocáis en un path diferente al original), cuando intentéis recompilarlo os generara un error : C1093 – detallando que no puede encontrar "stdafx.h". El concepto es que el proyecto genera y apunta determinadas referencias en tiempo de compilación, entonces la solución es hacer un “build>Clean Solution” desde “Generar>Proyecto>Limpiar”. Luego simplemente “F5” J
Espero vuestras valoraciones.
Pep Lluis,
** El proyecto esta realizado con la vesion 9 de Visual Studio. (2008)
A peticion vuestra os dejo el codigo, para utilizarlo con Visual Studio 2005. Solo teneis que crear nuevo proyecto 'winforms' arrastrando y soltando un 'ListBox' un 'Boton' y un SerialPort.
namespace SystemIOPorts_EN_C {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Resumen de Form1
/// Ejemplo de utilizacion del System.IO.Ports desde C++
/// (C) Pep Lluis 2008
///
///
/// Para realizar las pruebas es necesario insertar un
/// conector de 9 pins en el puerto serie utilizado
/// cortocircuitando (puenteando) los pines 2/3
///
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
// Abrir el puerto de comunicaciones
// inhibir la verificacion de error de llamadas entre hilos
//
this->serialPort1->Open();
CheckForIllegalCrossThreadCalls = false;
}
protected:
/// <summary>
/// Limpiar los recursos que se estén utilizando.
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
private: System::IO::Ports::SerialPort^ serialPort1;
private: System::Windows::Forms::ListBox^ listBox1;
private: System::Windows::Forms::Button^ button1;
protected:
private: System::ComponentModel::IContainer^ components;
private:
/// <summary>
/// Variable del diseñador requerida.
/// </summary>
#pragma region Windows Form Designer generated code
/// <summary>
/// Método necesario para admitir el Diseñador. No se puede modificar
/// el contenido del método con el editor de código.
/// </summary>
void InitializeComponent(void)
{
this->components = (gcnew System::ComponentModel::Container());
this->serialPort1 = (gcnew System::IO::Ports::SerialPort(this->components));
this->listBox1 = (gcnew System::Windows::Forms::ListBox());
this->button1 = (gcnew System::Windows::Forms::Button());
this->SuspendLayout();
//
// serialPort1
//
this->serialPort1->BaudRate = 115200;
this->serialPort1->DataReceived += gcnew System::IO::Ports::SerialDataReceivedEventHandler(this, &Form1::serialPort1_DataReceived);
//
// listBox1
//
this->listBox1->FormattingEnabled = true;
this->listBox1->Location = System::Drawing::Point(13, 13);
this->listBox1->Name = L"listBox1";
this->listBox1->Size = System::Drawing::Size(259, 95);
this->listBox1->TabIndex = 0;
//
// button1
//
this->button1->Location = System::Drawing::Point(197, 114);
this->button1->Name = L"button1";
this->button1->Size = System::Drawing::Size(75, 23);
this->button1->TabIndex = 1;
this->button1->Text = L"Enviar";
this->button1->UseVisualStyleBackColor = true;
this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(284, 147);
this->Controls->Add(this->button1);
this->Controls->Add(this->listBox1);
this->Name = L"Form1";
this->Text = L"C++ & System.IO.Ports";
this->ResumeLayout(false);
}
#pragma endregion
/// Enviar trama usando System.IO.Ports
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
this->serialPort1->Write(L"Hola Gente");
}
/// Leer los caracteres recibidos y añadirlos al ListBox
private: System::Void serialPort1_DataReceived(System::Object^ sender, System::IO::Ports::SerialDataReceivedEventArgs^ e) {
this->listBox1->Items->Add(serialPort1->ReadExisting());
}
};
}