OK, así que creó un método asíncrono estática. Eso deshabilitó el control que inicia la acción y cambia el cursor de la aplicación. Ejecuta la acción como una tarea y espera para terminar. El control vuelve a la persona que llama mientras espera. De modo que la aplicación sigue siendo receptiva, incluso mientras el ícono de ocupado gira.
async public static void LengthyOperation(Control control, Action action)
{
try
{
control.Enabled = false;
Application.UseWaitCursor = true;
Task doWork = new Task(() => action(), TaskCreationOptions.LongRunning);
Log.Info("Task Start");
doWork.Start();
Log.Info("Before Await");
await doWork;
Log.Info("After await");
}
finally
{
Log.Info("Finally");
Application.UseWaitCursor = false;
control.Enabled = true;
}
Aquí está la forma de código del formulario principal
private void btnSleep_Click(object sender, EventArgs e)
{
var control = sender as Control;
if (control != null)
{
Log.Info("Launching lengthy operation...");
CursorWait.LengthyOperation(control,() => DummyAction());
Log.Info("...Lengthy operation launched.");
}
}
private void DummyAction()
{
try
{
var _log = NLog.LogManager.GetLogger("TmpLogger");
_log.Info("Action - Sleep");
TimeSpan sleep = new TimeSpan(0, 0, 16);
Thread.Sleep(sleep);
_log.Info("Action - Wakeup");
}
finally
{
}
}
tuve que usar un registrador independiente para la acción ficticia (estoy usando Nlog) y mi principal registrador escribe para la interfaz de usuario (una rica caja de texto). No pude ver el cursor ocupado solo cuando estaba sobre un contenedor en particular en el formulario (pero no lo intenté muy duro). Todos los controles tienen una propiedad UseWaitCursor, pero no parece tener ningún efecto en los controles probé (tal vez porque no estaban en la parte superior?)
Aquí está el registro principal, que muestra las cosas que suceden en el orden que esperamos:
16:51:33.1064 Launching lengthy operation...
16:51:33.1215 Task Start
16:51:33.1215 Before Await
16:51:33.1215 ...Lengthy operation launched.
16:51:49.1276 After await
16:51:49.1537 Finally
esto no necesariamente cambiará el cursor - si el bucle de mensaje no se llamará durante el código de tiempo intensivo. para habilitarlo, necesita agregar _Application.DoEvents(); _ después del primer cursor establecido. – Amirshk
Probablemente desee intentarlo ... bloque final después de establecer Actual, también (asegurándose de que Current se restablezca a Predeterminado). – TrueWill
FYI, no pude hacer funcionar lo anterior, pero cambiándolo a this.cursor = cursores.esperacursor; funcionó. –