#xamarin #async-await #task
#xamarin #async-await #задача
Вопрос:
Мое приложение содержит процедуру, которая может быть длительной. Я хотел бы дать пользователям возможность остановить это.
Процедура:
void longRunningProcedure()
(она не имеет доступа к файловой системе или Интернету)
И внутри нее, после инициализации определенных переменных, вызывается doIt();
Я пробовал это:
async void longRunningProcedure()
и в рамках этой процедуры я попытался:
await Task.Run(() => doIt());
и пытались:
await Task.Run(async () => await doIt());
Но когда код достигает этой точки, я получаю эту ошибку:
The selected debug engine does not support any code executing on the current thread (e.g. only native runtime code is executing).
Unhandled Exception:
Android.Util.AndroidRuntimeException: <Timeout exceeded getting exception details> occurred
Долго выполняющийся код даже не выполняется вообще.
Что делать?
Комментарии:
1. Это потому, что ваш
doIt
метод дает сбой (исключение AndroidRuntimeException). О чем сообщается черезlogcat
?2. Вы можете ввести
try/catch
в методdoIt()
, чтобы получить больше информации об ошибке.3. Я сделал, и это сказало мне то, что мне нужно было знать. Краткая версия: runOnUiThread(() => {//доступ к пользовательскому интерфейсу. Это решило проблему.
4. Отлично! Не забудьте опубликовать это как ответ.
Ответ №1:
Я изменил void longRunningProcedure () на async void, как показано ниже:
асинхронный запуск аннулирует runLongRunningProcedure() {
await Task.Run(() => actualProcedure());
для моего приложения actualProcedure() просто:
void actualProcedure()
Теперь, помимо этого кода, у меня есть переменная,
bool cancelPressed
которая начинается как false
У меня есть кнопка и пункт меню, которые устанавливают значение true при нажатии.
И все это работает. Я могу запустить процедуру и остановить ее нажатием кнопки или меню.
Возникла еще одна проблема: длительно выполняющаяся процедура записывает данные в одно из текстовых полей приложения.
Выполнение этого привело к этой ошибке:
The selected debug engine does not support any code executing on the current thread (e.g. only native runtime code is executing).
ИТАК, мне пришлось изменить раздел записи данных на этот:
RunOnUiThread( () => {
txtBox.Text = modifiedData.ToString();
});
modifiedData — это переменная типа StringBuilder.
И все это работает.
В соответствующий момент во время процедуры у меня:
if (cancelPressed == true) return
На всякий случай я вложил это в try / catch.
Конечно, если бы я хотел уведомить пользователя об отмене процедуры (или о чем-либо еще во время ее выполнения) с помощью всплывающего сообщения, я должен сделать это:
RunOnUiThread(() => {
MakeToast(Message);
return;
});
У меня есть процедура под названием MakeToast, которая обрабатывает форматирование сообщения и т.д.