C# WinServiceBasic1: Crear un servicio básico en Windows

Los servicios (o demonio en Linux) son normalmente aplicaciones que corren de fondo (sin interfaz) y ofrecen como su nombre lo dice un servicio a otras aplicaciones, es muy común por ejemplo para implementar  protocolos de comunicaciones en red con otras máquinas mediante sockets TCP/UDP actuando como un servidor.  Otro uso muy común es como servidor de acceso a datos alojados en una máquina central.

Código del ejercicio en GitHub

Crear un servicio en VS 2012

En Visual Studio ahora te facilita crear aplicaciones de este tipo ya que ofrece un tipo de proyecto especifico “Windows Service”:

Visual Studio añade automáticamente una clase nueva Service1.cs heredada de System.ServiceProcess.ServiceBase.

Cambiamos el nombre de “Service1” por “MyNewService” buscando y reemplazando en todo el proyecto,

Añadir eventos de Windows

En la vista de diseño de Service1.cs arrastramos y añadimos un control “EventLog

VS le asigna un nombre eventLog1 a la nueva clase, podemos cambiar el nombre de la clase en las propiedades.

Ahora ya podemos añadir eventos para notificar de arranque / parada del servicio.

Instalar el servicio

Para crear un instalador usamos el botón derecho del ratón en la vista diseño Service1.cs sobre el fondo y el menú contextual seleccionamos “Add Installer”, revisamos las propiedades de “serviceInstaller1”, ServiceName debe estar definido como “MyNewService”, es importante elegir el tipo de arranque (lo dejamos en manual por el momento).

Para instalar el servicio hay que hacerlo mediante el interprete de comandos “Developer Command Prompt” incluido en VS.

Ahora vamos a la carpeta de salida donde está WinServiceBasic1.exe y ejecutamos:

installutil.exe WinServiceBasic1.exe

 

C# ThreadingBasics (II): Operaciones básicas con Threads

Código en GitHub

GetThreadState: Determinar el estado de un thread

El siguiente ejercicio nos permite obtener información valiosa sobre el estado de un Thread. Añadimos los siguientes métodos:t1

Y añadimos el siguiente código a la función principal Main:

t1

El Thread pasa por varios estados, podemos obtener el estado del hilo accediendo a la propiedad ThreadState que es un campo enumerado.

Inicialmente el estado del Thread t1 es Unstarted antes de ser arrancado. Cuando invocamos el método Start() inmediatamente pasa al estado Running. La llamada a Sleep provoca que pase al estado WaitSleepJoin. Finalmente la llamada Abort hace que pase a estado Aborted. El thread t2 finaliza con normalidad y su estado estado final es Stopped.

TheadPriority: Establecer prioridad en la ejecución de un thread


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Threading;

namespace TheadPriority
{
class ThreadSample
{
private bool _isStopped = false;

public void Stop()
{
this._isStopped = true;
}

public void CountNumbers()
{
long counter = 0;
while (!this._isStopped)
{
counter++;
}
Console.WriteLine("{0} with {1,11} priority " +
"has a count = {2,13}",
Thread.CurrentThread.Name,
Thread.CurrentThread.Priority,
counter.ToString("N0"));
}
}

class Program
{
static void RunThreads()
{
var sample = new ThreadSample();
var t1 = new Thread(sample.CountNumbers);
t1.Name = "t1";
var t2 = new Thread(sample.CountNumbers);
t2.Name = "t2";

t1.Priority = ThreadPriority.Highest;
t2.Priority = ThreadPriority.Lowest;

t1.Start();
t2.Start();

Thread.Sleep(TimeSpan.FromSeconds(10));
sample.Stop();
}

static void Main(string[] args)
{
Console.WriteLine("Main: current thread priority: {0}",
Thread.CurrentThread.Priority);
Console.WriteLine("Main: Calling RunThreads()");
RunThreads();
Console.WriteLine("Press any key to exit....");
Console.ReadLine();
}
}
}

C# ClassConstructor: Notas sobre constructores

Aquí van algunos ejemplos más avanzados con breves anotaciones sobre constructores de clases.

Los constructores son métodos especiales que se invocan cuando se instancia una clase, un método constructor nunca debe retornar nada (no es necesario definir el tipo de retorno en su declaración). Siempre que en una clase e define explicitamente un constructor el constructor por omisión o implícito es reemplazado por este.

El operador new crea un objeto nuevo y a continuación se invoca al constructor de la clase.

Constructor sobrercargadado

El método constructor también puede ser sobrecargado con varios métodos, con el mismo nombre (el de la clase) pero con diferentes parámetros:

c1

Llamadas entre constructores

A pesar de que pueda parece raro un constructor puede llamar a otro también. En el siguiente ejemplo primero se llama al constructor sin parámetros. Podemos usarlo para instanciar objetos comunes en el constructor sin parámetros y llamarlo desde constructores que aceptan diferentes tipos de inicializaciones especificas,

c2

Uso de la clase clsCamion:

c3

c4

También podemos pasar parámetros de un constructor a otro:

c5

 

Destructores

C# tiene un recolector de basura, el propio framework se ocupa de liberar los objetos que ya no usamos. En algunos casos tal vez no interese realizar una “limpieza” manual, para la clase clsCamion de arriba tendría el siguiente aspecto:

c6

Constructor de la clase base

Usando la palabra clave base podemos invocar el constructor de la clase base cuando usamos la herencia.

c7

 

 

Entradas relacionadas (clases):

Enlaces externos:

C# GetSetAccessDesc: Ejemplos descriptores de acceso con get/set

Algunos ejercicios básicos para entrenar con los descriptores de acceso get y set. Algunos usos que se me ocurren para get/set son: Validar los datos antes de permitir un cambio, obtener datos de otro origen de forma transparente (una base de datos por ejemplo), realizar una acción cuando se modifican datos (provocar un evento o cambiar el valor de otros campos relacionados).

clsDate: Control asignación de valores mediante set

En este ejemplo Month se declara como propiedad para asegurarnos que se establece un valor correcto para el mes comprendido entre 1 y 12.

getset1

Si por ejemplo tratamos de establecer un mes 15 no da error pero el valor no se establece y se mantiene a 0 (valor por defecto).

getset2

clsPerson: Descriptor acceso sólo get

El descriptor de acceso get debe devolver el valor de la propiedad, si solo definimos get la propiedad será solo de lectura, si intentamos modificar su valor el compilador no lo permitirá.

getset3

Uso de la clase clsPerson:

getset4

Cuando llamamos a Console.WriteLine entra en acción el descriptor get.

clsTrabajador: get para controlar si un campo es consistente

Podemos usar el descriptor de acceso get para devolver el valor de un campo haciéndolo consistente, en este caso empleamos un operador condicional ternario para comprobar si la cadena es null, en ese caso retornamos una cadena “NA” para indicar que el valor no se ha inicializado correctamente aún.

getset5

Entradas relacionadas:

C# Caja: Ejercicio con indexadores

En la entrada “C# class LibroCalificaciones: Acceso a propiedades con descriptores de acceso get / set” se estudio como se pueden emplear los descriptores de acceso get/set para controlar el acceso a los datos privados de una clase, por ejemplo:

idx1

Dentro de una clase podemos almacenar listas de datos  en arrays pòr ejemplo, podemos acceder a estos miembros usando indexadores, estos permiten el acceso indexado a las listas de elementos usando su índice numérico o usando un índice basado en nombres.

modificadorAcceso tipoRetorno this[ TipoIndice1 nombre1, TipoIndice2 nombre2, ...]
{
    get
    {
          // usa nombre1, nombre2...para acceder a datos
    }
    set
    {
          // usa nombre1, nombre2...para acceder a datos
    }
}

Vamos a demostrar su uso con una clase llamada clsCaja que contiene un array con 3 miembros privados de tipo double con las propiedades longitud, altura, anchura. Para poder indexar por nombre del atributo al array de doubles también definiremos un arreglo de string con los nombres de las propiedades.

idx2

Ahora siguiendo la sintaxis de arriba vamos a definir dos indexadores, el primero más sencillo de entender permite acceder a los elementos del arreglo usando un índice numérico de tipo int.

idx5

El segundo indexador utiliza un índice string que representa el nombre de la medida que queremos obtener (“longitud”,”altura”,”anchura”).

Cada indexador devuelve -1 si su descriptor de acceso get detecta un subíndice no valido. Lo mismo hace set set si tratamos de establecer un elemento no valido.

idx6

Ahora ya podemos usar los indexadores:

idx7

Entradas relacionadas:

Ejercicio completo


/*
* Created by SharpDevelop.
* User: i.landajuela
* Date: 21/12/2016
* Time: 18:34
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;

namespace Indexadores
{

//Ejemplo de uso de descriptores de acceso get/set para controlar
//el acceso a miembros privados de la clase
class TimePeriod
{
private double _seconds;
public double Seconds
{
get { return _seconds; }
set { _seconds = value; }
}
}

//-----------------------------------------------------------------

public class clsCaja
{
private string[] nombres = {"longitud","altura","anchura"};
private double[] medidas = new double[3];

public clsCaja(double longitud, double anchura, double altura)
{
medidas[0]=longitud;
medidas[1]=anchura;
medidas[2]=altura;
}

//indexador para acceder a medidas por el número de indice entero
public double this[int indice]
{
get
{
//valida indice a obtener
if ((indice<0) || (indice >= medidas.Length))
{
return -1;
}
else
return medidas[indice];
} //fin get
set
{
if (indice>=0 && indice < medidas.Length)
medidas[indice] = value;
} //fin set

} // fin de indexador numérico

public double this[string nombre]
{
get
{
//localiza elemento a obtener
int i=0;
while((i<nombres.Length)&&(nombre!=nombres[i]))
i++;
return (i==nombres.Length) ? -1 : medidas[i];
}
set
{
int i=0;
while((i<nombres.Length)&&(nombre!=nombres[i]))
i++;
if(i!=nombres.Length)
medidas[i] =value;
}
} //fin de indexador string

}


class Program
{
public static void Main(string[] args)
{
clsCaja objCaja = new clsCaja(10,20,30);


objCaja[0] = 80;
Console.WriteLine("caja[\"longitud\"]={0}",objCaja["longitud"]);
objCaja["longitud"] = 90;
Console.WriteLine("caja[\"longitud\"]={0}",objCaja["longitud"]);

Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}

Arduino: Sintaxis básica del lenguaje de programación

Estructura de un programa

Cuando creamos un nuevo programa (Archivo > Nuevo) el entorno de desarrollo crea por nosotros la estructura básica de la aplicación.

ar1

Las líneas de código que comienzan con “//” son comentarios para poder entender mejor la aplicación y no ejecutan ninguna instrucción cuando descargamos el programa a la placa Arduino.

El programa básico está formado por 2 funciones: setup y loop.

Más adelante explicaremos el propósito de cada una de ellas pero lo importante ahora es saber que es una función y cual es su sintaxis.

Funciones (Functions)

Las funciones permiten crear piezas modulares de código que pueden ser llamadas desde distintos puntos del resto del programa (si son recursivas pueden llegar a llamarse a si mismas).

La sintaxis básica de una función es la siguiente:

type NombreFunción(parámetros) { 
    //código de la función
}

Primero definimos el resultado que puede retornar (al punto del programa desde donde se llama) la función con el type, especificamos que tipo de dato va a retornar (por ejemplo un número entero o una cadena). Cuando el retorno es void significa que no retorna nada. A continuación definimos el nombre de la función (NombreFunción en el ejemplo de arriba),  entre paréntesis definimos los parámetros de la función especificando el tipo de dato y el nombre de la variable. Pongamos un ejemplo muy sencillo, queremos sumar dos números pasados como parámetros y que la función retorne el resultado de la suma.

La función tendrá el siguiente aspecto:

ar3

Si seguimos la explicación de arriba:

  • int: Indica que la función va a retornar un tipo de dato entero (la suma de dos números).
  • mySumFunction: Es el nombre de la función que nosotros hemos elegido.
  • Entre paréntesis los dos parámetros de entrada a la función, son los números a sumar, definidos de tipo entero o integer (int) y con los nombres de variable a y b.
  • Luego entre las llaves {} añadimos las instrucciones que realiza la función, en este caso sólo debe sumar los números de entrada que hemos llamado “a” y “b” y retornar el resultado usando la palabra clave return.

Para saber algo más consultar este enlace sobre declaración de funciones.

Para llamarla podemos hacer lo siguiente en otro punto del programa:

mySumFunction(2,3)

Bueno ahora que sabemos algo más sobre funciones volvemos al programa inicial básico, tenemos 2 funciones imprescindibles.

void setup()

Normalmente dentro de esta función establecemos los parámetros de configuración de nuestra aplicación. Es la primera función que ejecuta el programa cuando se carga y se ejecuta una sola vez. Por ejemplo usando la función pinMode podemos establecer un pin como E/S (Entrada o Salida) y usarla más adelante para encender un led conectado como salida (podemos ver algo más sobre PinMode en “Arduino ledblink: Hacer parpadear el led de la placa“).

ar4

void loop()

La función loop  es la siguiente que se ejecuta tras setup(). La función loop() hace lo que su nombre indica de forma secuencial ejecuta una a una las líneas de código y vuelve a empezar de forma cíclica. De esa forma en cada vuelta de ejecución podemos controlar los eventos que se producen en la placa.