Noticias

¡RECUERDA QUE SI ERES UN NUEVO USUARIO, DEBES PRESENTARTE PARA PODER PUBLICAR MENSAJES! | TENEMOS CANAL OFICIAL DE TELEGRAM: t.me/unity3dspain

Entendiendo las Coroutines (Co-Rutinas)

Iniciado por Ele, Octubre 04, 2015, 01:01:50 AM

Tema anterior - Siguiente tema
Octubre 04, 2015, 01:01:50 AM Ultima modificación: Octubre 04, 2015, 01:03:54 AM por Ele
Que son las Co-Rutinas?Las Co-Rutinas (Coroutines) son métodos que tienen la capacidad de pausarse y reiniciarse exactamente donde se quedo en el frame anterior. Para entenderlo mejor, consideremos el siguiente ejemplo de la documentación oficial :
1
2
3
4
5
6
7
void Fade() {
    for (float f = 1f; f >= 0; f -= 0.1f) {
        Color c = renderer.material.color;
        c.a = f;
        renderer.material.color = c;
    }
}
Si quisiéramos hacer una función como la anterior y la colocamos en el Update no tendría ningún efecto fade debido a que la funcion se ejecutara toda en el mismo frame y por ello no se renderizara los estados intermedios entre 1 y 0.En cambio si la colocáramos dentro de una Co-Rutina de la siguiente manera:
1
2
3
4
5
6
7
8
IEnumerator Fade() {
    for (float f = 1f; f >= 0; f -= 0.1f) {
        Color c = renderer.material.color;
        c.a = f;
        renderer.material.color = c;
        yield return null;
    }
}
La función se pausara en la linea donde esta el yield y el bucle for continuara en el siguiente frame sin perder el valor de la variable f de esta manera en cada frame se renderizara el cambio entre el valor de c.a y c.a -0.1.Adicionalmente las Co-Rutinas se pueden pausar cada n segundos con la clase WaitForSeconds como vemos en el siguiente ejemplo:

Intrínsicamente el SO de Windows nunca ha tenido la capacidad de ejecutar threads reales. Siempre ha utilizado la "partición de tiempo". Un ejemplo directo de que no es ejecución paralela es, crea una Coroutine con un while(1). Engaña al editor poniendo el yield return null fuera del bucle, para que crea que "volverá". Verás que cuelgue!

[quote author=iRobb" data-ipsquote-contapp="forums" data-ipsquote-contenttype="forums" data-ipsquote-contentclass="forums_Topic" data-ipsquote-contentid="28431" data-ipsquote-contentcommentid="115859">Intrínsicamente el SO de Windows nunca ha tenido la capacidad de ejecutar threads reales. Siempre ha utilizado la "partición de tiempo". Un ejemplo directo de que no es ejecución paralela es, crea una Coroutine con un while(1). Engaña al editor poniendo el yield return null fuera del bucle, para que crea que "volverá". Verás que cuelgue![/quote]a nivel de procesamiento de datos en teoría un procesador multi-nucleo debería ser capaz de ejecutar paralelamente sin ninguna segmentación de tiempo*. y fuera de unity cualquier aplicación puede correr tareas "paralelamente" en otros hilos, inclusive Unity implementa algunas clases que son totalmente asíncronas. y si colocas un task(operación asíncrona) dentro de un bucle infinito (update) y dicho task tiene a su vez en su cuerpo un bucle infinito(el bucle que planteas) de igual forma veras la aplicación congelarse aunque esta este en otro "subproceso" y usando una operación asíncrona, no es una prueba fiable de que corren o no en otro "hilo".pero si te fijas en las imágenes se puede ver en la ventana de subprocesos de visual studio que los métodos Update y CoRutina corren en el mismo subproceso lo que prueba que efectivamente no corren paralelamente, inclusive en una prueba mas afondo pude verificar que se ejecutan en el mismo orden en que son llamadas por StartCoroutine, por eso en el ejemplo que coloque la ejecución de la corutina se ejecutara antes que el método Update *Nota: https://en.wikipedia.org/wiki/Thread_(computing)" rel="external nofollow date=1443914085]https://en.wikipedia.org/wiki/Thread_(computing)

Hay que diferenciar las capacidades del procesador de las del SO. Y también diferenciar entre el multiproceso del SO y el de las aplicaciones que corren en ese SO.Una cosa es que, hoy en día, generen espacios de trabajo y procesamiento por aplicación. Pero dentro de la aplicación, no tendrás multiproceso. A eso me refiero. 

[quote author=iRobb" data-ipsquote-contapp="forums" data-ipsquote-contenttype="forums" data-ipsquote-contentclass="forums_Topic" data-ipsquote-contentid="28431" data-ipsquote-contentcommentid="115865 date=1443916307]Hay que diferenciar las capacidades del procesador de las del SO. Y también diferenciar entre el multiproceso del SO y el de las aplicaciones que corren en ese SO.Una cosa es que, hoy en día, generen espacios de trabajo y procesamiento por aplicación. Pero dentro de la aplicación, no tendrás multiproceso. A eso me refiero. [/quote]Microsoft desde la versión 7 de Windows soporta multithreading real sin ninguna segmentación de tiempo, el procesamiento es totalmente paralelo y tanto en C++ como C#, VB .NET y J# se puede correr tareas en diferentes "sub-procesos" corriendo totalmente en paralelo pero el proceso en si, es el ensamblado de la aplicación no tendría sentido tener varios procesos en una aplicación, pero si desde una aplicación ejecutas otro ensamblado bien sea que este en el mismo proyecto u otro de igual forma puedes correrlo en otro subproceso y totalmente en paralelo

Entonces el problema es semántico? O sea, se pueden ejecutar varios procesos en tiempo real (no en compartición de tiempo) en C++, C#, ... ? Pero Unity en C# no?

[quote author=iRobb" data-ipsquote-contapp="forums" data-ipsquote-contenttype="forums" data-ipsquote-contentclass="forums_Topic" data-ipsquote-contentid="28431" data-ipsquote-contentcommentid="115899 date=1443932036]Entonces el problema es semántico? O sea, se pueden ejecutar varios procesos en tiempo real (no en compartición de tiempo) en C++, C#, ... ? Pero Unity en C# no?[/quote]exacto, en unity puedes usar métodos asíncronos pero de forma implícita, es decir Application.LoadLevelAsync en efecto carga en un subproceso aparte el nivel pero no devuelve ningún Task por ello no se puede usar el keyword Await, ni se puede crear un Task, ni tampoco establecer un método como async.

Excelente aportación. Muchísimas gracias!   

Etiquetas: