Sunteți pe pagina 1din 26

3.9 Hilos en .

NET
 El framework da soporte a aplicaciones con hilos
(intercalados o ejecutados independientemente si hay
varios procesadores).
 Los hilos se pueden lanzar, destruir, pausar, suspender
hasta notificación, notificar, sincronizar…
 Espacio System.Threading
 Llamadas asíncronas: la ejecución de un método en un
hilo aparte. El hilo llamante sigue ejecutándose. Se
“bifurca” el flujo de ejecución
 El planificador del SO asigna ranuras de tiempo a cada
hilo (timeslices) de 15 a 30 ms (depende de la versión del
SO y del procesador).
Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 1
3.9 Hilos
 Hacer una pausa, en un hilo secundario o en el
principal
Thread.Sleep(1000) //milisegundos

 Thread.Sleep(0) cede automáticamente el tiempo


restante en el timeslice a hilos de la misma
prioridad. ¿Es buena idea?
 Datos sobre los hilos
– Creación: 200.000 ciclos. Destrucción: 100.000 ciclos
– 1 MB mem. virtual pila
– 2.000 a 8.000 ciclos / cambio de contexto
Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 2
3.9 Hilos. Clase
System.Threading.Thread
 El constructor recibe el método a ejecutar
 Ejemplo HilosMostrandoMensajes.cs (web, [1])
Thread th1 = new Thread(new ThreadStart(msg.Mostrar1));

3
3.9 Hilos en .NET
 Ejemplo HilosEjemplo1.cs (web, [2]). ¿Por qué?
public static void Main() {
Thread t = new Thread(new
ThreadStart(ThreadProc));
t.Start();

Console.WriteLine("Main thread: Do
some work.");

public static void Main() {


Thread t = new Thread(new
ThreadStart(ThreadProc));
t.Start();
Thread.Sleep(0);

Console.WriteLine("Main thread: Do some work.");
Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 4
3.9 Hilos. Uso con delegados
 Todo método referenciado en un delegado puede ser
llamado asíncronamente. Sólo delegados de 1 método
 Métodos en el delegado: BeginInvoke y EndInvoke
IAsyncResult BeginInvoke(<parámetros>, AsyncCallback cb, Object o)
<tipoRetorno> EndInvoke(<parámetrosRefOut>, IASyncResult ar)

 BeginInvoke crea un hilo y devuelve un obj con info de


ese hilo. Si más de 1 método: System.ArgumentException
 cb: delegado con métodos a ejecutar cuando termine el
hilo. Evita tener que ir comprobando si terminó (con
IAsyncResult.IsComplete):
public delegate void ASyncCallback(IASyncResult obj)

 o: cualquier info para los métodos de cb (accesible via


IAsyncResult.AsyncState)
Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 5
3.9 Hilos. Uso con delegados
 cb y o pueden ser null
 EndInvoke para recoger los resultados del método del
delegado. Espera a que finalice el hilo, y garantiza el
acceso actualizado a los parámetros ref y out.
 Si hubo una excepción, se lanza ahora
 Ejemplo
delegate void D(int valor);
D objDelegado = new D (F);
IAsyncResult hilo = objDelegado.BeginInvoke(3, new AsyncCallback(M), “prueba”);
// ... Hacer cosas
objDelegado.EndInvoke(hilo);

Método “M”
public static void M(IAsyncResult obj) {
Console.WriteLine(“Llamado a M() con {0}”, obj.AsyncState); }

Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 6


3.9 Hilos. Uso con delegados
 Salida
Pasado valor 3 a F()
Llamado a M() con prueba

 Atributo OneWay para métodos que no devuelvan


nada que interese: [OneWay] public void Método() {…}
 En el método de cb se pueden recoger los
resultados
public static void M(IAsyncResult iar) {
D objetoDelegado = (D) ((AsyncResult iar)).AsyncDelegate;
A partir de aquí podría llamarse a EndInvoke() a través de objetoDelegado
}

 Detalles en [6]
Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 7
3.9 Hilos. Clase
System.Threading.Thread
 ThreadStart no admite parámetros de salida.
¿Cómo se puede invocar a hilos con parámetros
de E/S?
 Ejemplo HilosPasoDeParametros.cs (web, [1])
– Clase intermediaria que lleva los parámetros y un
callback para devolver el resultado
– ¿Otra forma de hacerlo?

Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 8


3.9 Hilos. Clase
System.Threading.Thread
 Extracto de MSDN:
– El delegado ParameterizedThreadStart y la sobrecarga
del método Thread..::.Start(Object) facilitan el paso de
los datos a un procedimiento de subproceso, pero esta
técnica carece de seguridad de tipos puesto que se
puede pasar cualquier objeto a Thread..::.Start(Object).
Una forma más segura de pasar los datos a un
procedimiento de subproceso es colocarlo junto con los
campos de datos en un objeto de trabajo

 Ejemplo HilosPasoDeParametros2.cs (web, [1])


– Usar objeto de trabajo
Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 9
3.9 Hilos. Modificar la interfaz gráfica
 En WinForms, los controles de interfaz sólo se
pueden modificar desde el hilo principal. Desde
un hilo, esto daría problemas (¡al depurar!):

Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 10


3.9 Hilos. Modificar la interfaz gráfica
 A partir de .NET 2.0, se puede hacer con
delegados, anónimos
textbox.Invoke((MethodInvoker) delegate {
textbox.Text = msg;
});

o explícitos. V. ejemplos HilosActualizarGUI.cs y


HilosActualizarGUI_Error.cs (web, [4])

Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 11


3.9 Hilos. Modificar la interfaz gráfica
 Delegados explícitos:
// declaración del TextBox
private TextBox tbMsg;

// actualiza el texto del TextBox


private void UpdateText(string msg) { tbMsg.Text = msg; }

// delegado con la misma firma del método


public delegate void UpdateTextCallback(string msg);

 En el hilo:
tbMsg.Invoke(new UpdateTextCallback(this.UpdateText),
new object[]{“Texto generado desde otro hilo.”});

Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 12


3.9 Hilos. Modificar la interfaz gráfica
 Otra forma (BeginInvoke):
Label statusIndicator; Label counter;
button.Click += new EventHandler (StartThread);
delegate void StringParameterDelegate (string value); // delegado con la misma
signatura
// …actualizar
void UpdateCount() {… counter.Text = tmpCount.ToString(); }
void UpdateStatus(string value) {
if (InvokeRequired) { // not in the UI thread, so we need to call BeginInvoke
BeginInvoke(new StringParameterDelegate(UpdateStatus),
new object[]{value});
return; }
statusIndicator.Text = value; // Must be on the UI thread if we've got this far
}
Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 13
3.9 Hilos. Modificar la interfaz gráfica
 En el hilo:
UpdateStatus("Starting");

 O bien, usar un MethodInvoker (como antes)


MethodInvoker updateCounterDelegate = new
MethodInvoker(UpdateCount);

Invoke (updateCounterDelegate);

Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 14


3.9 Hilos. Modificar la interfaz gráfica
 Clase BackgroundWorker
– Ejecutar operaciones asíncronamente (descarga de
ficheros, cálculos complejos…)
– Invocar RunWorkerAsync. Al terminar, emite evento
RunWorkerCompleted

 V. ejemplos BackgroundWorkerExample y
BackgroundWorkerExample2 (Fibonacci)

Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 15


3.9 Hilos. Modificar la interfaz gráfica
 Clase BackgroundWorker BackgroundWorker
RunWorkerAsync(obj);
1
CancelAsync argumento
EVENTOS
DoWork
2
CALLBACKS ProgressChanged
RunWorkerCompleted
backgroundWorker1_DoWork(…DoWorkEventA 3a
rgs e) {… 3b
e.Result=ComputeFibonacci((int)e.Argument, ComputeFibonacci(int n,
worker, e);…} BackgroundWorker worker,
4 DoWorkEventArgs e) {…
backgroundWorker1_ProgressChanged {… worker.ReportProgress(percentComplete)
this.progressBar1.Value = e.ProgressPercentage …} …}
backgroundWorker1_RunWorkerCompleted
{…resultLabel.Text = e.Result.ToString()…}
Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 16
3.9 Hilos. IsBackground
 Un hilo puede ser en segundo plano (background)
o primer plano.
 Cuando todos los subprocesos de primer plano
que pertenecen a un proceso han finalizado,
Common Language Runtime finaliza el proceso.
Se detienen todos los subprocesos de fondo
restantes y no se finalizan.
 Ver ejemplo HilosBackgroundTest

Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 17


3.9 Hilos. Bloqueo de recursos
 Bloqueo de recursos en aplicaciones multihilo
lock (<objeto>) { <instrucciones> }

 Como <objeto> se puede usar this o, si es un


método de clase (estático), typeof(C)
class C {
public static void F() {
lock(typeof(C)) {
// ... Código al que se accede exclusivamente
}
}
}

Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 18


3.9 Hilos. Referencias
[1] Creación de hilos con parámetros en C#:
http://www.eslomas.com/index.php/archives/2006/01/16/creacion-
hilos-con-parametros-csharp/
[2] MSDN: clase Thread http://msdn.microsoft.com/es-
es/library/system.threading.thread.aspx
[3] Threading in Windows Forms
http://www.yoda.arachsys.com/csharp/threads/winforms.shtml
[4] MSDN: clase BackgroundWorker http://msdn.microsoft.com/es-
es/library/system.componentmodel.backgroundworker.aspx
[5] Sobre el uso de Thread.Sleep
http://msmvps.com/blogs/peterritchie/archive/2007/04/26/thread-sleep-is-
a-sign-of-a-poorly-designed-program.aspx
[6] El lenguaje de programación C#. J. A. González.
http://www.josanguapo.com/
Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 19
3.10 Atributos
[STAThread] static void Main()

– Declaraciones descriptivas para anotar


elementos: tipos, campos, métodos, y
propiedades, ensamblados...
[<atributo1>(<parametros1>), <atributo2>(<parámetros>), ...]

– Proporcionar metadatos o instrucciones para el


compilador (p.e. ejecución condicional)

– Recuperables por reflexión

Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 20


3.10 Atributos
– Predefinidos (diseño, ejecución condicional...):
AttributeUsage, Conditional, Obsolete,
Category, Description... (más de 200)

– Definidos por el programador: clases que


heredan de System.Attribute

– Pueden tener parámetros


[DllImport("super.dll", SetLastError=false, ExactSpelling=false)]

Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 21


3.10 Atributos
Definidos por el programador

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum)]
class AyudaAttribute: Attribute {
private string autor;
private string url;
public Ayuda(string URL) { url=URL; }
public string Autor {
set {autor = value;}
get {return autor;}
}}
Uso
[Ayuda("http://www.josan.com/Clases/B.html", Autor="José Antonio
González Seco")] class B {}
Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 22
3.10 Atributos
 Definidos por el programador.

 V. ejemplo AtributosDefinirYLeer

Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 23


3.10 Atributos
[STAThread] Usar Single-Threaded COM
Apartment si se necesita COM. Por defecto,
.NET no inicializa COM, salvo que se use un
control COM o arrastrar y soltar (DnD).

El otro modelo es multi-threaded apartment


(MTA), más eficiente, pero más complejo: exige
sincronización

– En aplicaciones con GUI, se recomienda usar


STA [2]
– VS genera el atributo para apps WinForms,
pero no para apps de consola
Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 24
3.10 Atributos

[Bindable(true), Category("Server"), Description(“bla, bla,…”),


DefaultValue(""),
EditorAttribute(typeof(System.Windows.Forms.Design.Fold
erNameEditor), typeof(UITypeEditor))]
public string DirectoryDecompression
{
get { return directoryDecompression;}
set { directoryDecompression = value; }
}

Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 25


3.10 Atributos. Referencias
[1] Atributos: http://www.programacion.com/tutorial/csharp/18/
Incluye un programa de ejemplo sobre cómo leerlos

[2] Sobre STAThread:


http://www.sellsbrothers.com/askthewonk/secure/WhatdoestheSTAThreadat
tri.htm

Desarrollo Basado en Componentes - Curso 10/11 - U. Murcia - J. Sáez 26

S-ar putea să vă placă și