martes, 11 de agosto de 2009

Controlando Threads en .Net

En otro post les mostré como crear Threads en .Net de cuatro formas diferentes, ahora veremos como controlarlos, detenerlos, etc.  A continuación uso de algunos métodos importantes de la clase Thread:

Thread.Join()

El método Join le dice al sistema que haga esperar a la aplicación hasta que el thread haya terminado. Un pequeño ejemplo para demostrar el uso:

static void Main(string[] args)
{
    ThreadStart operation = new ThreadStart(SomeWork);
    Thread theThread = new Thread();


    Console.WriteLine("Comienza la ejecución");
    theThread.Start();


    Console.WriteLine("Esperamos que termine");
    theThread.Join();


    Console.WriteLine("Listo");
    Console.Read();
}


static void SomeWork()
{
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine("Hello World #{0}", i);


        //simulamos un proceso
        Thread.Sleep(500);
    }
}




Thread.Priority



La clase Thread soporta el cambio de la prioridad de un Hilo de ejecución usando la enumeración ThreadPriority, la cual consiste en los siguientes valores:




  • Highest: Prioridad más alta.


  • Above: Un poco más alta que la normal.


  • Normal: Prioridad por defecto.


  • Below: Un poco más baja que la normal.


  • Lowest: Prioridad más baja.



Los threads son agendados basándose en ésta enumeración. En la mayoría de los casos se utiliza el valor por defecto (Normal). Modificar la prioridad de un Thread a Above o a Highest puede traer como consecuencia que se prive algún otro proceso importante del sistema, por lo que hay que hacerlo con precaución.



Thread.Abort()



Controlar Threads en tu aplicacón también requiere que seas capaz de detenerlos. La forma de hacerlo es usando el método Thread.Abort(), el cual cuando es llamado el systema lanza un ThreadAbortException en el subproceso no en el principal. Y sin importar si la excepción es controlada o no, el Thread se detiene justo despues de que se lanza la Excepción. Ejemplo:



static void Main(string[] args)

{

    Thread newThread = new Thread(new ThreadStart(TestThread));

    newThread.Start();

 

    //Simulamos proceso.

    Thread.Sleep(50);

    newThread.Abort();

    Console.WriteLine("Ready: {0} - Completed: {1}",

TestClass.IsReady, TestClass.IsCompleted);

Console.Read();

}


public class TestClass

{

    private static bool m_isReady;

    private static bool m_isCompleted;


    public static  bool IsCompleted

    {

        get { return m_isCompleted; }

        set { m_isCompleted = value; }

    }

 

    public static bool IsReady

    {

        get { return m_isReady; }

        set { m_isReady = value; }

    }

}

static void TestThread()

{

    TestClass.IsReady = true;

    //Simulamos un proceso.

    Thread.Sleep(200);

    TestClass.IsCompleted = true;
}



Si ejecutamos el código anterior nos podemos dar cuenta de que a la propiedad IsReady se le asigna correctamente el valor, pero en cambio a IsCompleted no. Esto es debido a que el abort se está ejecutando justamente despues del IsReady, por lo que IsCompleted nunca llega a asignársele el valor.



Por lo que nuestro código debería quedar de la siguiente manera:




static void TestThread()

{

    try

    {

        TestClass.IsReady = true;

        Thread.Sleep(200);

        TestClass.IsCompleted = true;

    }

    catch (ThreadAbortException ex)

    {

        Console.WriteLine(ex.Message);

        Console.WriteLine("Tratamos el error");

    }

    finally

    {

        Console.WriteLine("Cerramos conexiones, streams,etc");

    }

}



De esta manera manejamos correctamente la el aborto de ejecución del hilo y nuestra data o proceso quedan íntegros.



 



Continuaré este post pronto, y como siempre gracias por leer!

No hay comentarios:

Publicar un comentario