Escuché en algún lugar que C # 5 async-wait será tan increíble que no tendrás que preocuparte por hacer esto:
if (InvokeRequired)
{
BeginInvoke(...);
return;
}
// do your stuff here
Parece que la devolución de llamada de una operación en espera ocurrirá en el hilo original de la persona que llama. Eric Lippert y Anders Hejlsberg han afirmado varias veces que esta característica se originó a partir de la necesidad de hacer que las UI (particularmente las UI de dispositivos táctiles) sean más receptivas.
Creo que un uso común de dicha función sería algo como esto:
public class Form1 : Form
{
// ...
async void GetFurtherInfo()
{
var temperature = await GetCurrentTemperatureAsync();
label1.Text = temperature;
}
}
Si solo se utiliza una devolución de llamada, la configuración del texto de la etiqueta generará una excepción porque no se ejecuta en el hilo de la interfaz de usuario.
Hasta ahora no pude encontrar ningún recurso que confirme que este es el caso. ¿Alguien sabe de esto? ¿Hay algún documento que explique técnicamente cómo funcionará esto?
Proporcione un enlace de una fuente confiable, no solo responda "sí".
fuente
await
funcionalidad. Es solo una gran cantidad de azúcar sintáctica para el paso continuo . ¿Posiblemente hay otras mejoras no relacionadas con WinForms que se supone que ayudan? Sin embargo, eso caería dentro del marco .NET en sí, y no en C # específicamente.Respuestas:
Creo que te estás confundiendo algunas cosas, aquí. Lo que está pidiendo ya es posible usar
System.Threading.Tasks
,async
yawait
en C # 5 solo proporcionará un poco de azúcar sintáctica más agradable para la misma característica.Usemos un ejemplo de Winforms: suelte un botón y un cuadro de texto en el formulario y use este código:
Ejecútelo y verá que (a) no bloquea el subproceso de la interfaz de usuario y (b) no obtiene el error habitual "la operación de subprocesos no es válida", a menos que elimine el
TaskScheduler
argumento del últimoContinueWith
, en en cuyo caso lo harás.Este es un estilo de pase de continuación estándar de pantano . La magia ocurre en la
TaskScheduler
clase y específicamente en la instancia recuperada porFromCurrentSynchronizationContext
. Pase esto a cualquier continuación y le dirá que la continuación debe ejecutarse en cualquier hilo llamadoFromCurrentSynchronizationContext
método, en este caso, el hilo UI.Los aguardadores son un poco más sofisticados en el sentido de que son conscientes de en qué hilo comenzaron y en qué hilo debe suceder la continuación. Entonces, el código anterior se puede escribir un poco más naturalmente:
Estos dos deberían ser muy similares, y de hecho son muy similares. El
DelayedAddAsync
método ahora devuelve un enTask<int>
lugar de unint
, y por lo tantoawait
solo está aplicando continuaciones a cada uno de ellos. La principal diferencia es que está pasando el contexto de sincronización en cada línea, por lo que no tiene que hacerlo explícitamente como lo hicimos en el último ejemplo.En teoría, las diferencias son mucho más significativas. En el segundo ejemplo, cada línea del
button1_Click
método se ejecuta en el subproceso de la interfaz de usuario, pero la tarea en sí (DelayedAddAsync
) se ejecuta en segundo plano. En el primer ejemplo, todo se ejecuta en segundo plano , excepto la asignación a latextBox1.Text
que nos hemos asociado explícitamente al contexto de sincronización del hilo de la interfaz de usuario.Eso es lo que es realmente interesante
await
: el hecho de que un camarero puede entrar y salir del mismo método sin bloquear ninguna llamada. Usted llamaawait
, el hilo actual vuelve a procesar los mensajes, y cuando está hecho, el camarero retomará exactamente donde lo dejó, en el mismo hilo que dejó. Pero en términos de suInvoke
/BeginInvoke
contraste en la pregunta, yo ' Lamento decir que deberías haber dejado de hacerlo hace mucho tiempo.fuente
ArrayList
clase en un nuevo código. Apenas tengo experiencia con RX, yo mismo. Las personas aprenden lo que necesitan saber y comparten lo que ya saben, incluso si lo que ya saben está desactualizado. Esta respuesta podría estar desactualizada en unos pocos años.Sí, para el subproceso de la interfaz de usuario, la devolución de llamada de una operación de espera ocurrirá en el subproceso original de la persona que llama.
Eric Lippert escribió una serie de 8 partes sobre el tema hace un año: Fabulous Adventures In Coding
EDITAR: y aquí está Anders '// build / presentation: channel9
Por cierto, ¿notó que si pone "// build /" al revés, obtendrá "/ plinq //" ;-)
fuente
Jon Skeet dio una excelente presentación sobre los métodos asíncronos en C # 5, que puede ser extremadamente útil:
http://skillsmatter.com/podcast/home/async-methods
fuente