remarks generate example c# asynchronous unity3d .net-3.5 using

generate - params comments c#



Métodos asincrónicos en el uso de la declaración (2)

De los comentarios:

Entonces, ¿cómo puedo evitar esto? Solo agregue la palabra clave await?

No, no puedes hacer eso. (Y es por eso que la pregunta duplicada previamente propuesta no era de hecho un duplicado ... su escenario es sutilmente diferente.) Deberá retrasar el desecho hasta que la descarga se haya completado, pero esto es complicado por su necesidad de ejecutar dos declaraciones de programa más ( al menos ... es imposible saberlo con seguridad sin un ejemplo de código bueno, mínimo y completo ).

Creo que deberías cambiar al método de WebClient.DownloadFileTaskAsync() , ya que al menos simplificará la implementación, lo que simplifica la retención de la instrucción de using .

Puede abordar la otra parte del problema capturando el objeto Task devuelto y no esperar hasta que se hayan ejecutado sus otras declaraciones de programa:

using (WebClient wc = new WebClient()) { Task task = wc.DownloadFileTaskAsync(urlUri, outputFile); SomeMethod1(); SomeMethod2(); await task; }

De esta forma, la descarga puede iniciarse, sus otros dos métodos son llamados, y luego el código esperará la finalización de la descarga. Solo cuando se complete se saldrá del bloque de using , permitiendo que el objeto WebClient se elimine.

Por supuesto, en su implementación actual indudablemente está manejando un evento apropiado DownloadXXXCompleted XXX. Si lo desea, puede continuar usando el objeto de esa manera. Pero en mi humilde opinión, una vez que haya cambiado a usar await , es mucho mejor ponerlo después de await el código que necesita ejecutar al finalizar la operación. Esto mantiene todo el código relevante para la operación en un solo lugar y simplifica la implementación.


Si por algún motivo no puede usar await , deberá usar algún mecanismo alternativo para retrasar la eliminación del WebClient . Algunos enfoques le permitirán continuar using uso, otros requerirán que llame a Dispose() en el controlador de eventos DownloadXXXCompleted . Sin un ejemplo de código más completo, y una explicación clara de por qué await no es adecuado, no sería posible determinar con certeza cuál sería la mejor alternativa.


EDITAR:

Como confirmó que no tiene acceso para await en el código actual, aquí hay un par de otras opciones compatibles con código anterior ...

Una posibilidad es simplemente esperar en el mismo hilo después de comenzar la operación:

using (WebClient wc = new WebClient()) { object waitObject = new object(); lock (waitObject) { wc.DownloadFileCompleted += (sender, e) => { lock (waitObject) Monitor.Pulse(waitObject); }; wc.DownloadFileAsync(urlUri, outputFile); SomeMethod1(); SomeMethod2(); Monitor.Wait(waitObject); } }

(Nota: uno puede usar cualquier sincronización adecuada anterior, como ManualResetEvent , CountdownEvent , e incluso Semaphore y / o equivalentes "delgados. Uso el Monitor simplemente debido a su simplicidad y eficiencia, y los lectores se dan por hecho pueden ajustarse para acomodar su preferencia Medios de sincronización. Una razón obvia para preferir algo más que Monitor es que los otros tipos de técnicas de sincronización no correrán el riesgo de tener el controlador de eventos DownloadFileCompleted bloqueando en espera en los SomeMethod1() y SomeMethod2() para completarse. Si esto es importante depende, por supuesto, de cuánto tiempo tomarían esas llamadas de método en comparación con la descarga del archivo).

Lo anterior, sin embargo, bloqueará el hilo actual. En algunos casos, esto puede estar bien, pero la mayoría de las veces la operación se inicia en el subproceso UI, y ese subproceso no debe bloquearse mientras dure la operación. En ese caso, querrá renunciar al using completo y solo debe llamar a Dispose() desde el controlador de eventos de finalización:

WebClient wc = new WebClient(); wc.DownloadFileCompleted += (sender, e) => { wc.Dispose(); }; wc.DownloadFileAsync(urlUri, outputFile); SomeMethod1(); SomeMethod2();

Nota: Estoy usando C # en Unity, eso significa la versión .NET 3.5 , así que no puedo usar la palabra clave await o async .

¿Qué pasará con el uso de la declaración cuando coloque un método que funcione de forma asíncrona ?

using (WebClient wc = new WebClient()) { wc.DownloadFileAsync(urlUri, outputFile); } SomeMethod1(); SomeMethod2();

Como sabe, después de llamar al método DownloadFileAsync() se llamará SomeMethod1() que está fuera del bloque de using mientras DownloadFileAsync() todavía está funcionando . Así que ahora estoy realmente confundido sobre lo que sucedería con la sentencia using y el método asincrónico en este caso.

¿ Dispose() de wc en el momento correcto sin ningún problema?

Si no, ¿cómo puedo corregir este ejemplo?


System.Net.WebClient proporciona el evento DownloadFileCompleted . Puede agregar un controlador para ese evento y deshacerse del cliente en ese momento.