DelegateCommand asyn c ожидание против блокировки пользовательского интерфейса Task.Run - PullRequest
1 голос
/ 04 апреля 2020

Я хочу, чтобы мой пользовательский интерфейс отображал загрузочный оверлей после нажатия на мою кнопку.

Опция 1

MyCommand = new DelegateCommand(() => Task.Run(MyLongRunningTask);

private async Task MyLongRunningTask() {
    IsLoading = true;
    Thread.Sleep(5000);
    IsLoading = false;
}

Опция 2

MyCommand = new DelegateCommand(MyLongRunningMethod);

private async void MyLongRunningMethod() {
    IsLoading = true;
    Thread.Sleep(5000);
    IsLoading = false;
}

Опция 1 работает Вариант 2 нет. Я в порядке с этим, хотя я не понимаю, почему. Но мне бы очень хотелось, чтобы не нужно было оборачивать каждое выполнение в () => Task.Run (...).

Поскольку asyn c void кажется плохой идеей, я хотел бы сохранить используя задачи. Но я хочу сократить синтаксис, поэтому я пытаюсь как сумасшедший, но я не могу понять, как поместить () => Task.Run (..) в метод или класс, производный от DelegateCommand.

Почему Разве это не компилируется?

    private DelegateCommand GetAsyncCommand(Task t)
    {
        return new DelegateCommand(() => Task.Run(t));
    }

Что-нибудь похожее на это приводит либо к ошибкам времени компиляции, либо к тому, что мне приходится вызывать

MyCommand = GetAsyncCommand(MyLongRunningTask());

Из-за скобок () он мгновенно выполняет мою задачу на инстанциация.

Это кажется мне действительно запутанным. Если мне нужно обернуть все мои долго выполняющиеся задачи в эту конструкцию, почему я не могу создать более умную команду, которая просто делает это для меня с заданием?

Редактировать: я просто замечаю, что вариант 1 может не блокировать пользовательский интерфейс , но он проглатывает исключения, что ужасно.

Как настроить команду, которая не блокирует пользовательский интерфейс и выдает какие-либо исключения нормально?

1 Ответ

2 голосов
/ 04 апреля 2020

Thread.Sleep() блокирует текущий поток независимо от того, где он находится: в методе syn c или asyn c. В методе Asyn c есть еще один способ приостановить выполнение - await Task.Delay().

async не отвечает за Threading, async реализует состояние машины , которое выполняет ваш код асинхронно разделяет его на ожидаемые части. Task отвечает за многопоточность.

замените

Thread.Sleep(5000);

на

await Task.Delay(5000);

Обратите внимание, что async void - это плохая практика. Посмотрите .

...