Download accepts a wait handle (as an argument) and causes the calling
Document related concepts
no text concepts found
Transcript
Lenguaje C# Enfoque Marco Tecnológico en el que se sitúa Enfoque Programación Paralela Universidad Católica De Santa María Ingeniería de sistemas Autores: Noé Omar Alcázar Salas noe_fanclub@hotmail.com 1999800051 Armando Lazarte Aranaga Talía de la Cruz Hualpa Edgardo Ponce Escobedo Abstract This paper was made with purpose of explaining where does the C# programming language, takes place in the technological world of programming languages and the future of computing science, explaining why of it’s creation and why it’s use gonna be maybe the standard language used for internet programming & development. We explain too the characteristics of C# oriented to parallel programming, like creation and management of threads, also the classes that allow us to perform good synchronization in multithreading programs. 1. Introducción a C# Origen y necesidad de un nuevo lenguaje C# (leído en inglés "C Sharp" y en español "C Almohadilla") es el nuevo lenguaje de propósito general diseñado por Microsoft para su plataforma .NET. Sus principales creadores son Scott Wiltamuth y Anders Hejlsberg, éste último también conocido por haber sido el diseñador del lenguaje Turbo Pascal y la herramienta RAD Delphi. Aunque es posible escribir código para la plataforma .NET en muchos otros lenguajes, C# es el único que ha sido diseñado específicamente para ser utilizado en ella, por lo que programarla usando C# es mucho más sencillo e intuitivo que hacerlo con cualquiera de los otros lenguajes ya que C# carece de elementos heredados innecesarios en .NET. Por esta razón, se suele decir que C# es el lenguaje nativo de .NET La sintaxis y estructuración de C# es muy similar a la C++, ya que la intención de Microsoft con C# es facilitar la migración de códigos escritos en estos lenguajes a C# y facilitar su aprendizaje 1 a los desarrolladores habituados a ellos. Sin embargo, su sencillez y el alto nivel de productividad son equiparables a los de Visual Basic. Un lenguaje que hubiese sido ideal utilizar para estos menesteres es Java, pero debido a problemas con la empresa creadora del mismo -Sun-, Microsoft ha tenido que desarrollar un nuevo lenguaje que añadiese a las ya probadas virtudes de Java las modificaciones que Microsoft tenía pensado añadirle para mejorarlo aún más y hacerlo un lenguaje orientado al desarrollo de componentes. En resumen, C# es un lenguaje de programación que toma las mejores características de lenguajes preexistentes como Visual Basic, Java o C++ y las combina en uno solo. El hecho de ser relativamente reciente no implica que sea inmaduro, pues Microsoft ha escrito la mayor parte de la BCL usándolo, por lo que su compilador es el más depurado y optimizado de los incluidos en el .NET Framework SDK 2. Lenguaje C# y el Marco Tecnológico en el que se sitúa Para ello dividiremos esta sección en dos subsecciones: la primera de ellas dedicadas a .NET y la segunda de ellas dedicada a C#. Es importante notar que para entender en profundidad las características de C# es imprescindible estudiar antes .NET por lo que será la primera sección que tratemos. 2.1 Microsoft .NET NET no es más que la nueva generación de productos orientados al mundo de Internet y al de los dispositivos móviles que la multinacional norteamericana Microsoft presentó el pasado 22 de Julio en la conferencia PDC(Professional Developers Conference) celebrada en Orlando (Florida). .NET es anunciado por Microsoft como una nueva era en el desarrollo de aplicaciones tanto en entorno Windows, como en el resto de entornos que la soporten en un futuro, y la presentan como el estándar para Internet y todos los dispositivos que a ella se conecten. 2.2 Características de Microsoft .NET Utilización de XML La información procedente de distintos servicios suele tener formatos totalmente distintos de forma que el intercambio de información entre ellos supone un serio problema. Para salvar este contratiempo en .NET se utiliza el lenguaje XML(Extensible Markup Language). Toda la información que tenga que fluir de un servicio a otro será descrita con XML con el fin de establecer la correspondencia entre el formato de la información de cada servicio y los demás. Además, la comunicación entre servicios se realizarán utilizando el protocolo SOAP (Simple Object Access Protocol) que, como es de esperar, también está basado en XML y que permite invocar métodos, servicios, componentes y objetos de otros servicios remotos. Con este objetivo Microsoft ha construido una nueva herramienta para el desarrollo rápido de aplicaciones y servicios web llamada Visual Studio .NET que aún esta en versión beta. En la esta nueva versión del Visual Studio se incluyen los lenguajes Visual Basic, JScript, C++ y un nuevo lenguaje cuyo objetivo es sustituir a Java llamado C#, además, hay trabajando una conjunto de universidades y empresas privadas en incluir en .NET nuevos lenguajes de programación entre 2 los que se encuentran APL, CAML, Cobol, Haskell, Mercury, Ml, Oberon, Oz, Pascal, Perl, Python, Scheme, Smalltalk, e incluso JAVA en un proyecto liderado por la empresa Rational. Lo más atractivo quizás de este nuevo entorno de desarrollo es la capacidad de construir por ejemplo, parte de nuestra aplicación en Visual Basic y el resto en C++, C#, o incluso aprovechar una aplicación antigua sin tener que preocuparnos por la integración, con lo que facilitamos en gran medida la reutilización de código Para conseguir la integración, Microsoft se ha basado en la misma idea que utiliza Java para conseguir la portabilidad. La idea es construir una máquina virtual de forma que todo el código que escribamos se traduzca a un lenguaje intermedio común para todos los lenguajes, en este caso MSIL (Microsoft Intermediate Language) y en el caso de Java los bytecodes, que será el que la máquina virtual ejecutará. El principal problemas de Java es la eficiencia y este está derivado sin duda de la utilización de una máquina virtual. En este sentido Microsoft anuncia que la perdida de eficiencia en .NET va a ser sólo de un 10% aproximadamente, pero aún es pronto para hablar de eficiencia y tendremos que esperar a la versión definitiva del Visual Studio .NET para observar estos resultados. Para realizar esta afirmación, Microsoft se apoya en varios aspectos: 1. Por un lado, MSIL es de más alto nivel que otros lenguajes máquinas: trata directamente con objetos y tiene instrucciones para crearlos e inicializarlos directamente, puede llamar a métodos virtuales sobre objetos y manipular elementos de tablas directamente. Incluso tiene instrucciones para el manejo de excepciones. De forma que la máquina virtual debe ser más eficiente que la JVM. 2. Por otro lado, los compiladores utilizados son JIT (Just in TIme) que producen, o producirán, código nativo optimizado para el microprocesador que estemos usando, no compatible con toda la familia x86 como hacen otros JITs, de modo que al usar toda las capacidades de nuestro micro (registros, instrucciones propias del micro que usemos, 3 etc.) hacemos que el código se ejecute más rápido. En .NET hay tres tipos de compiladores JIT, los dos primeros nos permiten generar código nativo sin optimizar y optimizado. Estos JITs compilan a código nativo bajo demanda y una vez una parte está ya compilada, se guarda para utilizarla posteriormente evitando tener que volver a traducirla. El tercer tipo es un compilador de los de toda la vida que compila a nativo todo el código y guarda el resultado en disco. 2.3 El Núcleo de .NET. El Common Languaje Runtime (CLR) Para construir una máquina virtual común a todos los lenguajes primero hay que definir una serie de características comunes a todos ellos. Este conjunto de características comunes se engloban en el llamado Common Languaje Runtime(CLR). A continuación veremos algunas de las características que contempla el CLR: Es Orientado a objetos, no podría ser de otro modo. Soporta herencia (simple), polimorfismo, manejo de excepciones, etc. Posee un conjunto de tipos común estandarizado, el "Common Type System" (CTS). Esto elimina la ambigüedad en el sentido de que un entero se represente con 16 bits o 32 o que se soporte o no la herencia múltiple. Soporta metainformación para todos los tipos en tiempo de ejecución. Posee un conjunto de clases pertenecientes a .NET que encapsulan la mayoría de la funcionalidad del API win32 y otras tecnologías, como XML, etc. Proporciona opciones avanzadas para depurar aplicaciones. Proporciona un depurador que actúa entre lenguajes distintos, que nos permite recorrer la pila, etc. Proporciona ejecución virtual de código y manejo de memoria automático. Posee un recolector de basura. Proporciona traductores de lenguaje intermedio a código nativo. Y tiene un modelo de seguridad declarativo. El código que cumple con las restricciones del CLR se llama código "manejado", "managed code" en inglés. Todos los lenguajes que incluye .NET producen código manejado menos el C++ que posee características que se salen de las especificaciones, por ejemplo, el C++ permite la herencia múltiple que en el CLR no se permite. Para solucionar este problema se utilizan las llamadas extensiones de manejo (Managed Extension) que hacen que el código que escribamos en C++ se ajuste a CLR. Al tener un runtime común para todos los lenguajes, si escribimos dos clases con la misma funcionalidad, una de ellas codificada en Visual Basic y la otra codificada en C#, su traducción a lenguaje intermedio, es decir, a MSIL, será exactamente la misma. 3. ¿Donde Ingresa C#? Java se ha consolidado durante los últimos años como uno de los lenguajes más populares en el ámbito de Internet puesto que proporciona a los programadores la flexibilidad, la potencia y la portabilidad que las aplicaciones web precisan. Pero Microsoft no parecía nada contenta al ver que un lenguaje de la competencia triunfaba en un terreno en el que mantiene algunas de sus más encarnizadas batallas legales y tecnológicas. Por esta razón arremete ahora contra Sun con una nueva forma de ver la programación, .NET, en la que se incluye su candidato para sustituir a Java, C#. 4 C y C++ son dos de los lenguajes más utilizados en el campo de la ingeniería y la programación de sistemas. Se cuentan por millones los programadores expertos en ellos y no son menos los que de forma tradicional han venido resistiéndose a aprender Java. La principal razón es que C o C++ proporcionan el nivel de abstracción preciso para embarcarse en la construcción de una aplicación compleja, pero, al mismo tiempo, ofrecen mecanismos de bajo nivel que permiten a los programadores hacer uso de las características más avanzadas de las plataformas sobre las que se ejecutan sus programas. Por el contrario, Java está lastrado por su compromiso con la portabilidad y es inherentemente ineficiente. Microsoft se ha dado cuenta que en ese grupo de programadores podría encontrar una nueva línea de expansión para sus productos y es en este sentido en el que aparece C# que combina algunas de las características más avanzadas de Java con algunas de las más potentes de C y C++. La idea es convertirlo en el nuevo lenguaje de Internet y, por supuesto, en el lenguaje nativo para acceder a todos los servicios que en el futuro brindará .NET. El nuevo lenguaje de Microsoft, al igual que c y C++, permite programar fácilmente a bajo nivel. Gracias a esto, acceder a las características avanzadas de la plataforma sobre la que trabajamos, crear código muy eficiente en aquellos puntos de la aplicación que son críticos y acceder a las interfaces de programación de aplicaciones (APIs) existentes es perfectamente posible. En concreto, C# está especialmente preparado para acceder al API de Windows y los objetos COM+ y DLL del sistema, por lo que las aplicaciones escritas en este lenguaje podrán aprovechar todas las características de este popular sistema operativo y de .NET. Muchos dicen que si Java se puede considerar un C++ mejorado en cuestiones de seguridad y portabilidad, C# debe entenderse como un Java mejorado en todos los sentidos: desde la eficiencia hasta la facilidad de integración con aplicaciones tan habituales como Microsoft Office o Corel Draw. 3.1 Java y C# Lo cierto es que cualquier programador podría confundir perfectamente un programa sencillo en C# y creer que se trata de Java, puesto que en ambos se escribe de una forma muy parecida. No obstante, las diferencias son muchas y sus ventajas frente a Java se hacen patentes en el momento en que profundizamos un poco más. Los dos lenguajes son muy parecidos ya que ambos tienen recolector de basura, ambos son orientados a objetos, ninguno soporta la herencia múltiple, ambos tienen manejo de excepciones, etc. Pero como ya hemos dicho, C# añade algunas características bastante atractivas, como por ejemplo hacer el acceso objetos COM+ y a las DLLs totalmente transparente, ya que se asocia un objeto COM+ a una clase y a partir de ese momento los objetos de esa clase podrán hacer llamadas a los métodos del componente como lo haría cualquier otro objeto. Además, la sintaxis de C# es bastante parecida a Java, por ejemplo, los nombres de las librerías que nos proporcionan son muy parecidos, de forma que la traducción de un programa "sencillo" implementado en Java a C# es casi directa. 3.2 Características de C# Con la idea de que los programadores más experimentados puedan obtener una visión general del lenguaje, a continuación se recoge de manera resumida las principales características de C# Alguna de las características aquí señaladas no son exactamente propias del lenguaje sino de la 5 plataforma .NET en general. Sin embargo, también se comentan aquí también en tanto que tienen repercusión directa en el lenguaje, aunque se indicará explícitamente cuáles son este tipo de características cada vez que se toquen: Sencillez: C# elimina muchos elementos que otros lenguajes incluyen y que son innecesarios en .NET. Por ejemplo: El código escrito en C# es autocontenido, lo que significa que no necesita de ficheros adicionales al propio fuente tales como ficheros de cabecera o ficheros IDL El tamaño de los tipos de datos básicos es fijo e independiente del compilador, sistema operativo o máquina para quienes se compile (no como en C++), lo que facilita la portabilidad del código. No se incluyen elementos poco útiles de lenguajes como C++ tales como macros, herencia múltiple o la necesidad de un operador diferente del punto (.) acceder a miembros de espacios de nombres (::) Modernidad: C# incorpora en el propio lenguaje elementos que a lo largo de los años ha ido demostrándose son muy útiles para el desarrollo de aplicaciones y que en otros lenguajes como Java o C++ hay que simular, como un tipo básico decimal que permita realizar operaciones de alta precisión con reales de 128 bits (muy útil en el mundo financiero), la inclusión de una instrucción foreach que permita recorrer colecciones con facilidad y es ampliable a tipos definidos por el usuario, la inclusión de un tipo básico string para representar cadenas o la distinción de un tipo bool específico para representar valores lógicos. Orientación a objetos: Como todo lenguaje de programación de propósito general actual, C# es un lenguaje orientado a objetos, aunque eso es más bien una característica del CTS que de C#. Una diferencia de este enfoque orientado a objetos respecto al de otros lenguajes como C++ es que el de C# es más puro en tanto que no admiten ni funciones ni variables globales sino que todo el código y datos han de definirse dentro de definiciones de tipos de datos, lo que reduce problemas por conflictos de nombres y facilita la legibilidad del código. C# soporta todas las características propias del paradigma de programación orientada a objetos: encapsulación, herencia y polimorfismo. En lo referente a la encapsulación es importante señalar que aparte de los típicos modificadores public, private y protected, C# añade un cuarto modificador llamado internal, que puede combinarse con protected e indica que al elemento a cuya definición precede sólo puede accederse desde su mismo ensamblado. Respecto a la herencia -a diferencia de C++ y al igual que Java- C# sólo admite herencia simple de clases ya que la múltiple provoca más quebraderos de cabeza que facilidades y en la mayoría de los casos su utilidad puede ser simulada con facilidad mediante herencia múltiple de interfaces. De todos modos, esto vuelve a ser más bien una característica propia del CTS que de C#. Por otro lado y a diferencia de Java, en C# se ha optado por hacer que todos los métodos sean por defecto sellados y que los redefinibles hayan de marcarse con el modificador virtual (como en C++), lo que permite evitar errores derivados de redefiniciones accidentales. Además, un efecto secundario de esto es que las llamadas a los métodos serán más eficientes por defecto al no tenerse que buscar en la tabla de funciones 6 virtuales la implementación de los mismos a la que se ha de llamar. Otro efecto secundario es que permite que las llamadas a los métodos virtuales se puedan hacer más eficientemente al contribuir a que el tamaño de dicha tabla se reduzca. Orientación a componentes: La propia sintaxis de C# incluye elementos propios del diseño de componentes que otros lenguajes tienen que simular mediante construcciones más o menos complejas. Es decir, la sintaxis de C# permite definir cómodamente propiedades (similares a campos de acceso controlado), eventos (asociación controlada de funciones de respuesta a notificaciones) o atributos (información sobre un tipo o sus miembros) Gestión automática de memoria: Como ya se comentó, todo lenguaje de .NET tiene a su disposición el recolector de basura del CLR. Esto tiene el efecto en el lenguaje de que no es necesario incluir instrucciones de destrucción de objetos. Sin embargo, dado que la destrucción de los objetos a través del recolector de basura es indeterminista y sólo se realiza cuando éste se active -ya sea por falta de memoria, finalización de la aplicación o solicitud explícita en el fuente-, C# también proporciona un mecanismo de liberación de recursos determinista a través de la instrucción using. Seguridad de tipos: C# incluye mecanismos que permiten asegurar que los accesos a tipos de datos siempre se realicen correctamente, lo que permite evita que se produzcan errores difíciles de detectar por acceso a memoria no perteneciente a ningún objeto y es especialmente necesario en un entorno gestionado por un recolector de basura. Para ello se toman medidas del tipo: Sólo se admiten conversiones entre tipos compatibles. Esto es, entre un tipo y antecesores suyos, entre tipos para los que explícitamente se haya definido un operador de conversión, y entre un tipo y un tipo hijo suyo del que un objeto del primero almacenase una referencia del segundo (downcasting) Obviamente, lo último sólo puede comprobarlo en tiempo de ejecución el CLR y no el compilador, por lo que en realidad el CLR y el compilador colaboran para asegurar la corrección de las conversiones. No se pueden usar variables no inicializadas. El compilador da a los campos un valor por defecto consistente en ponerlos a cero y controla mediante análisis del flujo de control del fuente que no se lea ninguna variable local sin que se le haya asignado previamente algún valor. Se comprueba que todo acceso a los elementos de una tabla se realice con índices que se encuentren dentro del rango de la misma. Se puede controlar la producción de desbordamientos en operaciones aritméticas, informándose de ello con una excepción cuando ocurra. Sin embargo, para conseguirse un mayor rendimiento en la aritmética estas comprobaciones no se hacen por defecto al operar con variables sino sólo con constantes (se pueden detectar en tiempo de compilación) A diferencia de Java, C# incluye delegados, que son similares a los punteros a funciones de C++ pero siguen un enfoque orientado a objetos, pueden almacenar referencias a varios métodos simultáneamente, y se comprueba que los métodos a los que apunten tengan parámetros y valor de retorno del tipo indicado al definirlos. 7 Pueden definirse métodos que admitan un número indefinido de parámetros de un cierto tipo, y a diferencia lenguajes como C/C++, en C# siempre se comprueba que los valores que se les pasen en cada llamada sean de los tipos apropiados. Instrucciones seguras: Para evitar errores muy comunes, en C# se han impuesto una serie de restricciones en el uso de las instrucciones de control más comunes. Por ejemplo, la guarda de toda condición ha de ser una expresión condicional y no aritmética, con lo que se evitan errores por confusión del operador de igualdad (==) con el de asignación (=); y todo caso de un switch ha de terminar en un break o goto que indique cuál es la siguiente acción a realizar, lo que evita la ejecución accidental de casos y facilita su reordenación. Sistema de tipos unificado: A diferencia de C++, en C# todos los tipos de datos que se definan siempre derivarán, aunque sea de manera implícita, de una clase base común llamada System.Object, por lo que dispondrán de todos los miembros definidos en ésta clase (es decir, serán "objetos") A diferencia de Java, en C# esto también es aplicable a los tipos de datos básicos Además, para conseguir que ello no tenga una repercusión negativa en su nivel de rendimiento, se ha incluido un mecanismo transparente de boxing y unboxing con el que se consigue que sólo sean tratados como objetos cuando la situación lo requiera, y mientras tanto puede aplicárseles optimizaciones específicas. El hecho de que todos los tipos del lenguaje deriven de una clase común facilita enormemente el diseño de colecciones genéricas que puedan almacenar objetos de cualquier tipo. Extensibilidad de tipos básicos: C# permite definir, a través de estructuras, tipos de datos para los que se apliquen las mismas optimizaciones que para los tipos de datos básicos. Es decir, que se puedan almacenar directamente en pila (luego su creación, destrucción y acceso serán más rápidos) y se asignen por valor y no por referencia. Para conseguir que lo último no tenga efectos negativos al pasar estructuras como parámetros de métodos, se da la posibilidad de pasar referencias a pila a través del modificador de parámetro ref. Extensibilidad de operadores: Para facilitar la legibilidad del código y conseguir que los nuevos tipos de datos básicos que se definan a través de las estructuras estén al mismo nivel que los básicos predefinidos en el lenguaje, al igual que C++ y a diferencia de Java, C# permite redefinir el significado de la mayoría de los operadores -incluidos los de conversión, tanto para conversiones implícitas como explícitas- cuando se apliquen a diferentes tipos de objetos. Las redefiniciones de operadores se hacen de manera inteligente, de modo que a partir de una única definición de los operadores ++ y -- el compilador puede deducir automáticamente como ejecutarlos de manera prefijas y postifja; y definiendo operadores simples (como +), el compilador deduce cómo aplicar su versión de asignación compuesta (+=) Además, para asegurar la consistencia, el compilador vigila que los operadores con opuesto siempre se redefinan por parejas (por ejemplo, si se redefine ==, también hay que redefinir !=) También se da la posibilidad, a través del concepto de indizador, de redefinir el significado del operador [] para los tipos de dato definidos por el usuario, con lo que se 8 consigue que se pueda acceder al mismo como si fuese una tabla. Esto es muy útil para trabajar con tipos que actúen como colecciones de objetos. Extensibilidad de modificadores: C# ofrece, a través del concepto de atributos, la posibilidad de añadir a los metadatos del módulo resultante de la compilación de cualquier fuente información adicional a la generada por el compilador que luego podrá ser consultada en tiempo ejecución a través de la librería de reflexión de .NET . Esto, que más bien es una característica propia de la plataforma .NET y no de C#, puede usarse como un mecanismo para definir nuevos modificadores. Versionable: C# incluye una política de versionado que permite crear nuevas versiones de tipos sin temor a que la introducción de nuevos miembros provoquen errores difíciles de detectar en tipos hijos previamente desarrollados y ya extendidos con miembros de igual nombre a los recién introducidos. Si una clase introduce un nuevo método cuyas redefiniciones deban seguir la regla de llamar a la versión de su padre en algún punto de su código, difícilmente seguirían esta regla miembros de su misma signatura definidos en clases hijas previamente a la definición del mismo en la clase padre; o si introduce un nuevo campo con el mismo nombre que algún método de una clase hija, la clase hija dejará de funcionar. Para evitar que esto ocurra, en C# se toman dos medidas: Se obliga a que toda redefinición deba incluir el modificador override, con lo que la versión de la clase hija nunca sería considerada como una redefinición de la versión de miembro en la clase padre ya que no incluiría override. Para evitar que por accidente un programador incluya este modificador, sólo se permite incluirlo en miembros que tengan la misma signatura que miembros marcados como redefinibles mediante el modificador virtual. Así además se evita el error tan frecuente en Java de creerse haber redefinido un miembro, pues si el miembro con override no existe en la clase padre se producirá un error de compilación. Si no se considera redefinición, entonces se considera que lo que se desea es ocultar el método de la clase padre, de modo que para la clase hija sea como si nunca hubiese existido. El compilador avisará de esta decisión a través de un mensaje de aviso que puede suprimirse incluyendo el modificador new en la definición del miembro en la clase hija para así indicarle explícitamente la intención de ocultación. Eficiente: En principio, en C# todo el código incluye numerosas restricciones para asegurar su seguridad y no permite el uso de punteros. Sin embargo, y a diferencia de Java, en C# es posible saltarse dichas restricciones manipulando objetos a través de punteros. Para ello basta marcar regiones de código como inseguras (modificador unsafe) y podrán usarse en ellas punteros de forma similar a cómo se hace en C++, lo que puede resultar vital para situaciones donde se necesite una eficiencia y velocidad procesamiento muy grandes. Compatible: Para facilitar la migración de programadores, C# no sólo mantiene una sintaxis muy similar a C, C++ o Java que permite incluir directamente en código escrito en C# fragmentos de código escrito en estos lenguajes, sino que el CLR también ofrece, a través de los llamados Platform Invocation Services (PInvoke), la posibilidad de acceder a código nativo escrito como funciones sueltas no orientadas a objetos tales como las DLLs de la API Win32. Nótese que la capacidad de usar punteros en código inseguro 9 permite que se pueda acceder con facilidad a este tipo de funciones, ya que éstas muchas veces esperan recibir o devuelven punteros. También es posible acceder desde código escrito en C# a objetos COM. Para facilitar esto, el .NET Framework SDK incluye una herramientas llamadas tlbimp y regasm mediante las que es posible generar automáticamente clases proxy que permitan, respectivamente, usar objetos COM desde .NET como si de objetos .NET se tratase y registrar objetos .NET para su uso desde COM. Finalmente, también se da la posibilidad de usar controles ActiveX desde código .NET y viceversa. Para lo primero se utiliza la utilidad aximp, mientras que para lo segundo se usa la ya mencionada regasm. 4. Creación y manejo de hilos en C# La clase principal para la creación de hilos y el manejo de estos es System.Threading.Thread, esta clase tiene una cantidad métodos de los cuales resaltaremos los siguientes: Start(): inicia la ejecución, de un hilo, lo pone listo para ejecución. Thread thread = new Thread(new ThreadStart( WriteData )); thread.Start(); WriteData is la funcion ejecutada por el hilo. protected void WriteData() { string str ; for ( int i = 0; i<=10000; i++ ) { str = "Secondary Thread" + i.ToString(); Console.WriteLine(listView1.ListItems.Count, string[]{""} ); Update(); } } str, 0, new Suspend(): suspende el hilo indefinidamente, si este esta ya suspendido no pasa nada. if (thread.ThreadState == ThreadState.Running ) { thread.Suspend(); } Resume() : Activa al hilo suspendido, poniéndolo en listo para ejecución. if (thread.ThreadState == ThreadState.Suspended ) { thread.Resume(); } 10 Interrupt(): interrumpe a un hilo que se encuentra en un estado wait, sleep, join Join(): blocks a calling thread until the thread terminates. Sleep(int x) : Suspende un hilo por una cantidad de tiempo especifico en milisegundos. While(s==0) {thread.Sleep(5000);} Abort(): Termina la participación de un hilo. if ( thread.IsAlive ) { thread.Abort(); } Esta clase tambien cuenta con numero de propiedades interasantes IsAlive: si regresa verdadero significa que el hilo no a sido abortado o terminado. Name :pone ó obtiene el nombre del hilo. Priority: pone ó obtiene la planificación de prioridad del hilo. ThreadState: obtiene un valor con el estado del hilo. using System; using System.Threading ; namespace LearnThreads { class Thread_App { public static void First_Thread() { Console.WriteLine("First thread created"); Thread current_thread = Thread.CurrentThread; string thread_details = "Thread Name: " + current_thread.Name + "\r\nThread State: " + current_thread.ThreadState.ToString()+ "\r\n Thread Priority level:"+current_thread.Priority.ToString(); Console.WriteLine("The details of the thread are :"+ thread_details); Console.WriteLine ("first thread terminated"); } public static void Main() { ThreadStart thr_start_func = new ThreadStart (First_Thread); 11 Console.WriteLine ("Creating the first thread "); Thread fThread = new Thread (thr_start_func); fThread.Name = "first_thread"; fThread.Start (); //starting the thread } }} Mostramos la siguiente tabla donde se explica los métodos mencionados, en el lenguaje nativo de la información Thread management functions A mapping between Java's java.lang.Thread methods and their equivalent in C#'s System.Threading.Thread object Java C# setDaemon( boolean method IsBackground on) property isDaemon() method IsBackground property isAlive() method IsAlive get property Notes set Makes a given thread a daemon thread (the program will terminate when all that is left are daemon threads). get Returns true if the thread is a background thread. Returns true if the thread is alive. interrupt() method Interrupt() method While in Java this sets the "interrupted status" of the thread and can be checked to see whether a thread has been interrupted, there is no such equivalent check in C#. However, in C#, calling Interrupt on a thread that is not blocking will cause the next blocking call to automatically unblock. isInterrupted() method Returns true if this thread has been interrupted. n/a sleep( long millis Sleep( int ) and sleep( long millisecondTimeout ) millis, int nanos ) and Sleep( System.TimeSpan ) methods join(), and join( long millis ), and join( long millis, int nanos ) A static call that pauses the thread of execution for a given amount of time or until the thread is interrupted -- this method will throw a java.lang.InterruptedException in Java and a System.Threading. ThreadInterruptedException in C# (remember that all C# exceptions are run-time). Join(), Join( int Unlike the Java join methods which are simply millisecondTimeout ), timeouts, the C# versions return a boolean upon and Join( termination to signify whether the thread died System.TimeSpan ) 12 methods methods (true) or the timeout expired (false). suspend() method Suspend() method Functionally the same -- the C# methods exhibit the same properties that caused the suspend() method in java.lang.Thread to be deprecated. This method is deadlock-prone: if a thread holding a lock on a system-critical resource is suspended, then no other threads can access the resource until the former thread is resumed. resume() method Resume() method Resumes a suspended thread. stop() method Abort() method See "Stopping Threads" following this table. La propiedad System.Threading.Thread.ThreadState define el estado en el que se encuentra un hilo en un determinado momento. Cuando un hilo es creado, el estado de este es Unstarted. Cuando un hilo ejecuta el metodo start() el estado del hilo entra en Running, y se queda en este estado, hasta que no sea suspendido, mandado a dormir, abortado ó termine la ejecución del hilo. Cuando el hilo es suspendido cambia al estado suspendido, hasta que otro hilo lo reactive, y regrese al estado Running, cuando el hilo es abortado o ha llegado a su fin el estado en que entra es Stopped (estado final en que terminaran todos los hilos en condiciones nomales). Existe otro estado del hilo llamado Background el cual nos indica sin un hilo se encuentra en ejecutándose en primer plano (foreground) o según plano (background). Acá mostramos la tabla en de lo estados de un hilo inglés para un mejor entendimiento Member Aborted Description The thread is in the Stopped state. The ThreadAbort method has been invoked on the thread, but the thread has AbortRequested not yet received the pending System.Threading.ThreadAbortException that will attempt to terminate it. The thread is being executed as a background thread, as opposed to a foreground thread. This state is controlled by setting the IsBackground Background property of the Thread class. The thread has been started, it is not blocked, and there is no pending Running ThreadAbortException. The thread has stopped. Stopped The thread is being requested to stop. This is for internal use only. StopRequested The thread has been suspended. Suspended SuspendRequested The thread is being requested to suspend. The Thread.Start method has not been invoked on the thread. Unstarted 13 WaitSleepJoin The thread is blocked as a result of a call to Wait, Sleep or Join methods. La Propiedad priority de un hilo significa la importancia en ejecutar esa tarea de una manera mas rápida asignándole de esta manera mayor cantidad de recursos del computador. Existen dos posiciones para hacer cumplir las necesidades de prioridad una es asignando mayor cantidad de tiempo de procesador para una tarea( lo cual pondría en peligro la multitarea) o dar mayor frecuencia de utilización del procesador a estos. Los diferentes valores de prioridad en C# son los sguientes: Highest, AboveNormal, Normal, BelowNormal, Lowest 5. Sincronización de hilos C# nos ofrece una serie de clases que nos ayudan a manejar problemas de acceso a recursos compartidos, sincronización entre procesos, creación de operaciones atómicas. De esta manera también demos saber evitar lo problemas clásicos de data- races, deadlocks and starvation. Las clases de sincronización son las siguientes: La clase Monitor La clase monitor es utilizada en caso en que queremos evitar el acceso concurrente a un pedazo de código en un tiempo dado. Todos lo métodos en esta clase son static, así que no necesitamos instanciar la clase esta clase los metodos que utiliza esta clase son los siguientes: · Enter, TryEnter · Exit · Pulse / PulseAll · Wait Uno puede sincronizar el acceso a un pedazo de código bloqueando o desbloqueando un objeto particular los metodos Monitor.Enter, Monitor.TryEnter and Monitor.Exit son usados para bloquear o desbloquear un objeto.Una vez que un bloqueo se hace a una porción de código (Monitor.Enter(object)), ningun otro hilo podra bloquear la misma región de codigo. El bloqueo puede ser liberado usando Monitor.Exit(object) or Monitor.Wait. Cuando el desbloqueo es realizado, el método Monitor.Pulse and Monitor.PulseAll apunta y avisa al siguiente hilo en la cola de listos para bloquear la porción de código public { void some_method() 14 int a=100; int b=0; Monitor.Enter(this); //say we do something here. int c=a/b; Monitor.Exit(this); } //en este caso nunca se llegará a ejecutar la sección de desbloqueo ya que ocurrirá un error, si queremos evitar esto tendremos que utilizar la función lock que actúa igual que Monitor.Enter(this); public void some_method() { int a=100; int b=0; lock(this); //say we do something here. int c=a/b; } Mostramos la siguiente tabla de los métodos de la clase monitor en ingles(lenguaje nativo de la información) para un mejor entendimiento Thread synchronization The keywords to know when wanting to synchronize actions between threads in the two languages Java C# Notes synchronized lock The C# lock statement is actually syntactic sugar for using the System.Threading.Monitor class's Enter and Exit methods Object.wait() Monitor.Wait( object obj ) There is no wait method inherent to an Object. To wait for a signal, the System.Threading.Monitor class needs to be used instead. Both of these methods need to be executed in synchronized blocks Object.notify() Monitor.Pulse( object obj ) See the notes for Monitor.Wait above Object.notify() Monitor.PulseAll( object obj ) See the notes for Monitor.Wait above Mutex Class 15 El comportamiento de esta clase es similar al comportamiento de la clase Monitor explicado anteriormente Public { void some_method() int a=100; int b=20; Mutex firstMutex = new Mutex(false); FirstMutex.WaitOne(); //some kind of processing can be done here. Int x=a/b; FirstMutex.Close(); } WaitOne: accepts a wait handle (as an argument) and causes the calling thread to wait until the current wait handle signal by calling Set. WaitAny: accepts an array of wait handles (as an argument) and causes the calling thread to wait until any one of the specified wait handles signal by calling Set. WaitAll: accepts an array of wait handles (as an argument) and causes the calling thread to wait until all specified wait handles signal by calling Set Señales: Son interrupciones asíncronas que se envían de un hilo a otro en el mismo proceso. Conceptualmente son como las señales de UNIX, salvo que se envían entre hilos en vez de entre procesos. Las señales se pueden enviar, capturar o ignorar. b) Mútex: Es como un semáforo binario. Su funcionamiento es el de un mútex típico. Puede tener un estado entre dos posibles, cerrado o no cerrado. Si se intenta cerrar un mútex no cerrado, se cierra, y el hilo que realizó la llamada continúa su ejecución. Pero si se intenta cerrar un mútex ya cerrado, el hilo que realizó la llamada se bloquea hasta que otro hilo libere la cerradura del mútex. Cuando más de un hilo espera bloqueado por un mútex, cuando éste se libera, se desbloquea a un único hilo. También existen una llamada en la que se intenta cerrar el mútex, pero si no se puede hacer durante un determinado intervalo de tiempo, finaliza y devuelve un error al hilo que realizó la llamada. c) Semáforos: Los semáforos son más lentos que los mútex, pero su funcionamiento es similar, y existen ocasiones en que son necesarios. Su funcionamiento es el habitual descrito por Dijkstra. Existen operaciones P y V para el semáforo, pero además existe una operación DOWN que si no tiene éxito durante cierto intervalo de tiempo, termina. Synchronization Events Hemos visto que los objetos de exclusión mutua, monitores se utilizan normalmente para sincronizar accesoa datos, en cambio los eventos se utilizan para que un hilo pueda comunicar a otro que un evento ha ocurrido. AutoResetEvent Class Se utilizan cuando las funciones de espera lock no pasan automáticamente al estado ocupado. 16 ManualResetEvent Class Se utilizan cuando las funciones de espera lock pasan automáticamente al estado ocupado. Interlocked Class Sirve para sincronizar el acceso a variable que están siendo accedidas por muchos hilos, provenido el aseguramiento de operaciones atómicas. Entre sus métodos tenemos Interlocked.Increment y Interlocked.Decrement que sirven para incrementar ó decrementar una variable de manera atómica, también poner un valor en una variable utilizando Interlocked.Exchange, tambien comparar el valor de dos variables, si son iguales remplaza una de las variables con un valor determinado Interlocked.CompareExchange. ReaderWriterLock class Esta clase define un bloqueo en el proceso de escritura y lectura. Esta clase ofrece sincronización de lectura y escritura. Cualquier cantidad de hilos pueden leer los datos concurrentemente pero al escribir, y el bloqueo sucede cuando alguien quiere actualizar una de las variables. Los hilos lectores pueden acceder a bloque cuando no haya hilos escritores, y los hilos escritores accederán al bloque cuando no haya hilos escritores ni lectores. ReaderWriterLock.AcquireReaderLock, ReaderWriterLock.ReleaseLock funciones de bloqueo y desbloqueo Pasar de ser hilo escritor a ser hilo lector y viceversa ReaderWriterLock.UpgradeToWriterLock, ReaderWriterLock.DowngradeFromWriterLock. 6. Conclusiones Parece ser que existirá una disputa tecnológica entre Sun Microsystems y Microsoft Corp. En lo que es programación web debido al gran avance que Microsoft ha dado con la creación de .NET y de la portabilidad de las aplicaciones. El C# como abanderado de .NET aparenta tener mayor potencia en progrmación y velocidad de las aplicaciones creadas, debido a que junta las características de C++ y de JAVA además que MSIL (Microsoft Intermediate Language) parece ser mas potente en ejecución que los bytecodes de JAVA Nos hemos dado cuenta que programar en C# requiere un buen entendimiento de la tecnología de objetos ya que es casi un lenguaje puro OO. Por habra primero que entender a la perfección el manejo de clases y objetos, toda la tecnología de objetos para tener éxito programando en C# Respecto a las caracteríticas de C# en lo que es programación paralela, son superiores a las de C++ y JAVA ya que las clases son mas robustas en detalles como propiedades, métodos que no evitan estar programando demás. En términos generales el fundamento teórico de elementos de sincronización como mutex, señales, semaforos son muy parecidas a las de todos los lenguajes pero las clases en C# cuentan con mayor cantidad de propiedades que nos permiten analizar el estado de estos objetos. 17 La orientación de objetos de este lenguaje es determinante para entender la utilización de los objetos de sincronización ya que todos estos toman como parámetros objetos callers. Las características generales de lenguaje de programación son demasiado útiles y desestrezantes para la programación ya que cuenta con muchos clases de control, ademas de las propiedades inherentes del lenguaje explicadas al inicio del paper. 7. Referencias http://tdg.lsi.us.es/ pagina que contiene la explicación clara de C# y .NET y su correspondencia de acá sacamos la parte de C# y .Net www.C#Corner.com pagina que contiene infinidad de artículos publicados y información de C# en Inglés de acá sacamos la parte hilos. www.csharphelp.com Pagina contiene infinidad de artículos de C# en Ingles, también usamos esta pagina para la parte hilos 18