Итак, я создал статический асинхронный метод. Это отключило элемент управления, который запускает действие и изменяет курсор приложения. Он запускает действие как задачу и ожидает завершения. Контроль возвращается к вызывающей стороне, пока он ждет. Таким образом, приложение остается отзывчивым, даже когда значок «занят» вращается.
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;
}
Вот код формы основной формы
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
{
}
}
Мне пришлось использовать отдельный регистратор для фиктивного действия (я использую Nlog), и мой основной регистратор пишет в пользовательский интерфейс (расширенное текстовое поле). Мне не удалось отобразить курсор занятости только при нахождении над конкретным контейнером в форме (но я не очень старался). Все элементы управления имеют свойство UseWaitCursor, но, похоже, это не влияет на элементы управления. Я пытался (возможно, потому что они не были на вершине?)
Вот основной журнал, который показывает, что происходит в том порядке, в котором мы ожидаем:
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