OK, j'ai donc créé une méthode asynchrone statique. Cela a désactivé le contrôle qui lance l'action et modifie le curseur d'application. Il exécute l'action en tant que tâche et attend la fin. Le contrôle revient à l'appelant pendant qu'il attend. Ainsi, l'application reste réactive, même lorsque l'icône occupée tourne.
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;
}
Voici le code du formulaire 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
{
}
}
J'ai dû utiliser un enregistreur distinct pour l'action factice (j'utilise Nlog) et mon enregistreur principal écrit dans l'interface utilisateur (une zone de texte riche). Je n'ai pas pu obtenir le curseur occupé uniquement sur un conteneur particulier du formulaire (mais je n'ai pas essayé très fort.) Tous les contrôles ont une propriété UseWaitCursor, mais cela ne semble pas avoir d'effet sur les contrôles J'ai essayé (peut-être parce qu'ils n'étaient pas au top?)
Voici le journal principal, qui montre les choses qui se passent dans l'ordre que nous attendons:
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