#c# #.net #xamarin.forms #async-await
#c# #.net #xamarin.forms #async-await
Вопрос:
Я внедряю Xamarin.Формирует приложение, используя Nuget MVVMHelpers: https://github.com/jamesmontemagno/mvvm-helpers
Я пытаюсь использовать команду AsyncCommand из этой библиотеки, которая описана в этом блоге: https://johnthiriet.com/mvvm-going-async-with-async-command
Я хочу, чтобы была реализована следующая цепочка:
- Пользователь нажимает на кнопку загрузки
- Откроется диалоговое окно загрузки, и пользователь выберет файл
- Текст файла запрашивается на richTextEdit
Чтобы справиться с этим, я использую следующую ViewModel:
public class UploadViewModel : BaseViewModel
{
private string[] _allowedFileTypes;
private string _fileText;
private bool _hasFile;
public AsyncCommand UploadFileCommand { get; private set; }
public string FileText { get { return _fileText; } set { SetProperty(ref _fileText, value); } }
public bool HasFile { get { return _hasFile; } set { SetProperty(ref _hasFile, value); } }
public UploadViewModel()
{
Title = "Upload";
_allowedFileTypes = new string[] { "txt" };
UploadFileCommand = new AsyncCommand(UploadFileAsync, x => IsNotBusy);
}
private async Task UploadFileAsync()
{
if (IsBusy)
return;
try
{
IsBusy = true;
var fileData = await CrossFilePicker.Current.PickFile(_allowedFileTypes);
if (fileData == null)
return;
StreamReader reader = new StreamReader(fileData.GetStream());
FileText = await reader.ReadToEndAsync();
HasFile = !string.IsNullOrWhiteSpace(FileText);
}
finally
{
IsBusy = false;
}
}
}
Обратите внимание, что BaseViewModel взят из MVVMHelpers
Моя проблема в том, что в асинхронном методе UploadFileAsync
isBusy = false
достигается до завершения работы. Поэтому я думаю, что это проблема моего понимания async / await. Я прочитал несколько блогов и ответов на Stackoverflow, но не понял. Также пытался запустить GetStream()
в собственной задаче, но с тем же результатом.
ОБНОВЛЕНИЕ: представление в Xamarin.Forms XAML выглядит следующим образом:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage.BindingContext>
<viewModels:UploadViewModel />
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout>
<button:SfButton Text="Upload File" Command="{Binding UploadFileCommand}" IsVisible="{Binding IsNotBusy}" Margin="5,5,5,5"/>
<richTextEditor:SfRichTextEditor IsVisible="{Binding HasFile}" Text="{Binding FileText}" ReadOnly="True" VerticalOptions="FillAndExpand" ShowToolbar="False"/>
<busyindicator:SfBusyIndicator x:Name="busyindicator" IsBusy="{Binding IsBusy}" AnimationType="DoubleCircle"/>
</StackLayout>
</ContentPage.Content>
Комментарии:
1. Я хотел вам помочь и привел здесь минимально воспроизводимый пример. Первоначально я смог смоделировать вашу проблему, однако в какой-то момент это прекратилось, к сожалению, я не могу вспомнить, что я сделал. Может быть, вы можете его использовать?
2. Привет, @Leander, спасибо за пример. Вы используете асинхронные методы, не ожидая их и не возвращая задачу. Насколько я знаю, это плохая практика. Я думаю, что в вашем случае все работает синхронно, и именно поэтому оно работает. В моем случае я использую анимацию загрузки в пользовательском интерфейсе, которая зависнет, если мой код будет выполняться без await .
3. Вы уверены, что опубликованный код воспроизводит проблему?
4. Привет @StephenCleary я добавил макет представления. Это точно воспроизводит проблему. Я использую компоненты syncfusion, но вы должны быть в состоянии заменить это простой кнопкой.
5. @Sebi Хотя я был убежден, что мой код уже был асинхронным, я немного изменил его, и теперь
PollBusy
он определенно больше не синхронный. Сноваfinally
выполняется послеtry
блока. Может быть, вы также можете опубликовать MVCE?