OK, quindi ho creato un metodo asincrono statico. Ciò ha disabilitato il controllo che avvia l'azione e modifica il cursore dell'applicazione. Esegue l'azione come un'attività e attende che finisca. Il controllo ritorna al chiamante mentre attende. Quindi l'applicazione rimane reattiva, anche mentre l'icona di occupato 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;
}
Ecco il codice dal modulo principale
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
{
}
}
Ho dovuto usare un logger separato per l'azione fittizia (sto usando Nlog) e il mio logger principale sta scrivendo nell'interfaccia utente (una casella di testo ricca). Non sono stato in grado di visualizzare il cursore di occupato solo quando si trovava su un particolare contenitore nel modulo (ma non ci ho provato molto.) Tutti i controlli hanno una proprietà UseWaitCursor, ma non sembra avere alcun effetto sui controlli Ho provato (forse perché non erano in cima?)
Ecco il registro principale, che mostra le cose che accadono nell'ordine che ci aspettiamo:
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