c# - objeto - promesa de compraventa sobre bien embargado
No se puede llamar al inicio en una tarea tipo promesa. la excepción viene (3)
Estoy creando una aplicación de escritorio wpf simple. UI tiene solo un botón y un código en un archivo .cs como.
private void Button_Click_2(object sender, RoutedEventArgs e)
{
FunctionA();
}
public void FunctionA()
{
Task.Delay(5000).Start();
MessageBox.Show("Waiting Complete");
}
Pero sorprendentemente la línea Task.Delay(5000).Start();
está lanzando una InvalidOperationException
:
No se puede llamar al inicio en una tarea tipo promesa.
¿Alguien puede ayudar por qué es así?
Como dijo Servy, la tarea ya ha comenzado, así que todo lo que queda por hacer es esperar (.Wait ()):
private void Button_Click_2(object sender, RoutedEventArgs e)
{
FunctionA();
}
public void FunctionA()
{
Task.Delay(5000).Wait();
MessageBox.Show("Waiting Complete");
}
Está obteniendo ese error porque la clase Task
ya comenzó la tarea antes de dársela. Solo debes llamar a Start
en una tarea que crees llamando a su constructor, y ni siquiera deberías hacerlo a menos que tengas un motivo convincente para no iniciar la tarea cuando la creas; si desea que se inicie de inmediato, debe usar Task.Run
o Task.Factory.StartNew
para crear y comenzar una nueva Task
.
Entonces, ahora sabemos simplemente deshacernos de ese molesto Start
. Ejecutará su código y encontrará que el cuadro de mensaje se muestra de inmediato, no 5 segundos después, ¿qué pasa con eso?
Bueno, Task.Delay
solo te da una tarea que se completará en 5 segundos. No detiene la ejecución del hilo durante 5 segundos. Lo que quiere hacer es tener algún código que se ejecute después de que termine esa tarea. Para eso es ContinueWith
. Le permite ejecutar un código después de que se realiza una tarea determinada:
public void FunctionA()
{
Task.Delay(5000)
.ContinueWith(t =>
{
MessageBox.Show("Waiting Complete");
});
}
Esto se comportará como se espera.
También podríamos aprovechar la palabra clave await de C # 5.0 para agregar continuaciones más fácilmente:
public async Task FunctionA()
{
await Task.Delay(5000);
MessageBox.Show("Waiting Complete");
}
Si bien una explicación completa de lo que está sucediendo aquí está más allá del alcance de esta pregunta, el resultado final es un método que se comporta de manera muy similar al método anterior; mostrará un cuadro de mensaje 5 segundos después de llamar al método, pero el método volverá [casi] de inmediato en ambos casos. Dicho esto, await
es muy poderoso y nos permite escribir métodos que parecen simples y directos, pero sería mucho más difícil y complicado escribir con ContinueWith
directamente. También simplifica en gran medida el manejo de errores, sacando muchos códigos repetitivos.
Prueba esto.
private void Button_Click_2(object sender, RoutedEventArgs e)
{
FunctionA();
}
public async void FunctionA()
{
await Task.Delay(5000);
MessageBox.Show("Waiting Complete");
}