Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - [D4N93R]

#1741
Bueno este es un tuto que escribí hace unos 6 meses, y ahora lo comparto con la comunidad del hacker.net. Si encuentran algún error o algo, me avisan, La idea es ayudarnos y recordar que todos somos humanos.. :)

La programación Multi-Threading es uno de los aspectos peores manejados entre los programadores, por eso antes de comenzar a utilizarlos, debemos saber en qué consiste.



¿Qué es un hilo de ejecución?

Un Hilo de ejecución o Thread es el contexto en donde se está ejecutando una porción de código, es decir, desde que comienza un programa éste fluye a través de un Hilo de ejecución (de ahora en adelante Thread). Antes de que los sistemas operativos soportaran Multi-Threading solamente un Thread era el que llevaba el flujo de la aplicación. Ahora con las nuevas tecnologías y lo avanzados que están los sistemas operativos podemos crear nuevos Threads para desarrollar aplicaciones que las aprovechen y así mejorarlas en varios aspectos como el rendimiento o simplemente mejorar la interfaz de usuario.



Ok ya se que es Multi-Threading, pero ¿Cuándo debo utilizarlo?

Existen varias ocasiones en las que es ideal el uso de un Thread o varios en conjunto para realizar una tarea. Por ejemplo:

Caso 1:

En un formulario tienes una consulta que se tarda aproximadamente 1 minuto, la consulta se ejecuta en el evento Click de un botón llamado button1 (jeje) , el usuario al hacer click y lanzar el evento va a tener que esperar que el proceso termine, mientras ésto ocurre el formulario se deshabilita ya que el Thread que ejecuta el proceso es el mismo que dibuja la ventana, por lo cual aparece el famoso "(No Responde)" en el título.

- Solución: Lanzar el proceso en otro Thread y deshabilitar el botón hasta que termine. Mientras se ejecuta avisar al usuario, ya sea el progreso o simplemente el estado.

Caso 2:

Tienes dos procesos (A y B) que se tienen que ejecutar al mismo tiempo, y no tienen nada que ver uno con otro y normalmente ejecutarías A y luego B para luego continuar el flujo de la aplicación, pero ¿Qué pasaría si A se tarda 30 segundos y B 45 segundos?

- Solución: utilizar dos hilos paralelos para la ejecución y así tomar ventaja de los Procesadores nuevos multi-núcleo.



Existen otros casos, de los que estaremos hablando en próximos post!



Ahora por fin, ¿Cómo lo hago?

Antes de comenzar necesitamos definir un último concepto, llamado Delegado. Un delegado es un tipo de dato especial el cual tiene como función "apuntar" a un método cualquiera. Para que ésto ocurra el delegado debe de estar declarado de forma tal que coincida con la firma del método (Entiéndase firma por los parámetros).

Para todos los ejemplos se usará el siguiente método: void DoProcess(string text).

Cómo uso un delegado:

Primero creamos un delegado que coincida con la firma del método:

delegate void DoProcessDelegate(string text);

luego instanciamos:

DoProcessDelegate delegate = new DoProcessDelegate(DoProcess);

y ejecutamos:

string a = delegate("hola mundo");

Si! así de fácil!

Y ahora bien, existen varias vías para crear un proceso nuevo e iniciarlo:

Utilizando un Delegado

Instanciamos y apuntamos hacia el método:

DoProcessDelegate delegate = new DoProcessDelegate(DoProcess);

Llamamos al método BeginInvoke del delegado para comenzar la ejecución asíncrona donde nos pide los parámetros del delegados más dos, cuales son: AsyncCallback y un object.

El AsyncCallback hace referencia al método que se llama cuando se completa el proceso asíncrono.

El object lo recibe el método que apunta el AsyncCallback.

Ahora tenemos otro método llamado void ProcessEnded(IAsyncResult obj) y pasamos "prueba" como token, aunque debería ser un valor diferente en casos de que se ejecute varias veces la llamada a BeginInvoke En éste caso podemos pasar un Guid: Guid.NewGuid().

delegate.BeginInvoke("Hola Mundo", new AsyncCallback(ProcessEnded), "prueba");

Ahora el  método DoProcess se ejecuta de forma asíncrona y luego el ProcessEnded cuando éste último termine y le llega como parámetro "prueba".

Y ¿Qué pasa si nuestro DoProcess retorna algún valor? pues simplemente en el método ProcessEnded llamamos a delegate.EndInvoke(obj). El obj es el parámetro de ProcessEnded.



Utilizando la clase Thread

Otra forma de ejecutar un método asíncrono es usando la clase Thread. Ésta clase es la base de la ejecución de los Threads. Su funcionamiento es un poco más complicado. Ojo! su funcionamiento más no su llamado, es decir, mediante el uso de la clase Thread tenemos a la mano un conjunto de opciones y clases un poco más avanzadas sobre todo para el tema de la sincronización, de el cual les hablaré en otro post.

Básicamente la clase tiene dos constructores, uno pide un delegado ThreadStart y otro pide un delegado ParametrizedThreadStart, el primero es para apuntar hacia un método sin parámetros y el otro hacia uno con un parametro tipo object.

Ambos funcionan de la misma manera por lo que vamos a utilizar ThreadStart. Ahora tenemos un método nuevo void DeleteAllFiles();

Thread myThread = new Thread(new ThreadStar(DeleteAllFiles));

ahora simplemente para iniciar el thread solo hace falta llamar al método:

myThread.Start();

Éste tiene una sobrecarga de un parametro object para el ParametrizedThreadStart.



La clase ThreadPool

Un pequeño ejemplo del uso de ThreadPool es el siguiente :

El método QueueUserWorkItem tiene un parámetro el cual es un delegado de tipo WaitCallback, que es la referencia al método que se va a ejecutar. También tiene una sobrecarga para pasar un object. 

public void main(string[] args)

{

        ThreadPool.QueueUserWorkItem(new WaitCallback(MyMethod));

         Thread.Sleep(5000);  //El Sleep "duerme" el hilo acual, sino hacemos ésto,

                                          //otra cosa u proceso el hilo del ThreadPool no

                                          //se ejecutará ya que el hilo principal se termina.

}

public void MyMethod(object obj)

{

       //Algún proceso

}



El componente BackgroundWorker

El BackgroundWorker es un componente que podemos arrastrar hasta el formulario, control de usuario o simplemente declararlo dentro de nuestro código. Ejmplo básico de su uso:

static void main(string[] args)

{
     BackgroundWorker worker = new BackgroundWorker();
     worker.DoWork+=new DoWorkEventHandler(worker_DoWork);
     worker.RunWorkerAsync(); //aquí tenemos una sobre carga para pasarle

                                                 //un object al método worker_DoWork

}

static void worker_DoWork(object sender, DoWorkEventArgs e)

{

     // éste código se ejecuta asíncrono

     //en el parámetro DoWorkEventArgs encontramos el object que se envia desde RunWorkerAsync()

     //además de la posiblidad de cancelar en e.Cancel, y de enviar un valor de retorno por e.Result

}



Además de proveernos con funcionamiento asíncrono, el BackgroundWorker nos ofrece maneras para que nuestros métodos "reporten" el progreso del proceso, además de la capacidad de permitir la interrupción de manera fácil de nuestro Thread. El resultado de la operación que se envía a través de e.Result lo podemos encontrar fácilmente suscribiéndonos al evento RunWorkerCompleted del  BackgroundWorker.



Bueno ésto fue todo por ahora! Pronto publicaré más artículos cómo éste y de otros tipos también!..

Gracias por leer! y no se olviden de comentar :)
#1742
.NET (C#, VB.NET, ASP) / Re: Raw Sockets y VB.NET
13 Diciembre 2009, 19:34 PM
Apuesto a que estás haciendo un Port Scanner! jeje :P 

Dale dale que si se puede en .net! ;)

Saludos! :D
#1743
Deberías expresarte un poco mejor, me costó bastante entender varias partes.. Lee el post varias veces antes de publicarlo para que sea fácil de entender..

Un saludo..
#1744
Tengo dudas sobre la solución?
Tienes que guardar la data o simplemente cuando se cierra se pierde todo?
En ese caso, Tienes que usar BD o puedes escribirlo en archivos de Texto?

Te digo esto porque si vas a usar BD entonces no vas a necesitar los arrays, en caso de que no tengas que usar BD entonces tampoco usas array  :P sino que tienes que usar la clase List<T> que implementa una lista genérica...

Un saludo..
#1745
Échale un ojo a Reporting Services.. es mucho más fácil.. y creo que va bien para lo que necesitas..

Saludos..
#1746
No tengo aun VS, me ha dado de todo bajarlo jaja mi conexión anda lenta.. Espero complile xD

Pruebalo asi jajaj debería escribir hasta que se llene el disco/unidad/o lo que sea jaja de un exception y termine el ciclo =P


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

using System.IO; // No olvidar desde aquí.

namespace CMD_Serie
{
    class Program
    {
        private const string FILE_NAME = "Archivo.txt";

        static void Main(string[] args)
        {
            using (StreamWriter sw = File.CreateText(FILE_NAME))
            {
                while(true)
                {
                   try
                   {
                        sw.WriteLine("Hola viteh!!");
                   }
                   catch { break; // =P}
                   
                }
            }
        }
    }
}

#1747
Exacto, una clase de conexión es mucho mejor.. y Si haces un modelo de componentes mejor aún!
#1748
Amigo Lince,

Unas recomendaciones, espero no se me olvide ninguna, jeje ;D

1) el proceso de traer data, conectarte, etc, siempre dentro de un try. y SIEMPRE cierra las conexiones en el finaly..

2) En las consultas trata de limpiar la entrada de datos, y para que no puedan ejecutar codigo arbitrario.

3) O si prefierees, mejor aun, utiliza Stored Procedures, en vez de text queries.. De esta forma le agregas seguridad y velocidad al proyecto.

Mucha exito en la universidad..!  :P

#1749
Igual puedes optimizar tus rutinas! eso siempre lo tendrás que hacer!

Saludos!
#1750
Comenzamos un tema fácil en .Net:

- Escribir un chat sencillo con server.
- Todo debe ser programado utilizando modelos de componentes.
- Agregarle Multithreading al chat.
- Crear base de datos de usuario, conversaciones y log de chat
- Migrar la aplicación a Asp.net utilizando el mismo modelo de componentes

Todo debe ser lo más sencillo posible..

Intentaré ayudarlos si suben los proyectos, así que programen con claridad..

Un saludo!! :)