C# Подождите, пока метод asyn c не завершится sh, прежде чем продолжить - PullRequest
0 голосов
/ 12 января 2020

У меня проблема. Я создал это ViewModel для моего CollectionView:

public class TemplateListViewModel
{
    public double WidthHeight { get; set; }

    public ICommand LoadTemplates => new Command(MyHandler);
    public int CurrentTemplateCountReceived;
    public bool HitBottomOfList = false;
    public ObservableCollection<TemplateSource> sourceList { get; set; }


    public TemplateListViewModel()
    {
        CurrentTemplateCountReceived = 0;
        sourceList = new ObservableCollection<TemplateSource>();

        var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
        var width = mainDisplayInfo.Width;
        var density = mainDisplayInfo.Density;
        var ScaledWidth = width / density;

        WidthHeight = (ScaledWidth / 2);

        loadingTemplates += onLoadingTemplates;
        LoadTemplateList();
    }

    private event EventHandler loadingTemplates = delegate { };

    private Task LoadTemplateList()
    {
        loadingTemplates(this, EventArgs.Empty);
        return null;
    }

    private async void onLoadingTemplates(object sender, EventArgs args)
    {
        if (HitBottomOfList == false)
        {
            List<Template> templateList = await App.RestService.GetTemplates(App.User, CurrentTemplateCountReceived);

            if (templateList != null)
            {
                foreach (var template in templateList)
                {
                    ImageSource source = ImageSource.FromUri(new Uri("mysite.org/myapp/" + template.FileName));
                    TemplateSource templateSource = new TemplateSource { Id = template.Id, Source = source, WidthHeight = WidthHeight, FileName = template.FileName };
                    sourceList.Add(templateSource);
                }

                CurrentTemplateCountReceived = sourceList.Count;
            }
            else
            {
                HitBottomOfList = true;
            }
        }
    }

    bool handling = false;

    public void MyHandler()
    {
        // already handling an event, ignore the new one
        if (handling) return;

        handling = true;

        LoadTemplateList();

        handling = false;
    }
}

Теперь, что это делает: он собирает местоположения изображений с моей веб-страницы, а затем создает ImageSources для этих собранных изображений и добавляет его к SOURCELIST. Теперь я также создал RemainingItemsThresholdReachedCommand="{Binding LoadTemplates}" в xaml, поэтому он собирает больше данных, когда почти достигает дна CollectionView, вызывая эту команду: ICommand LoadTemplates => new Command(MyHandler);. Это событие вызывается много раз, поэтому я создал этот обработчик:

public void MyHandler()
{
    // already handling an event, ignore the new one
    if (handling) return;

    handling = true;

    LoadTemplateList();

    handling = false;
}

, который проверяет, есть ли уже обработанное событие.

Проблема в том, что в MyHandler, LoadTemplateList() не ожидает результата, что приводит к многочисленным вызовам на мою веб-страницу, потому что handling будет немедленно установлен на false!

Теперь, как мне ждать LoadTemplateList()?

Ответы [ 2 ]

1 голос
/ 12 января 2020

Теперь, как мне ждать LoadTemplateList ()?

с ключевым словом await:

handling = true;

await LoadTemplateList();

handling = false;

Однако он все равно вернется рано, потому что код делает что-то классное EventHandler. Если вы просто удалите весь этот лишний код и переместите асинхронный код в LoadTemplateList, он будет работать нормально:

public class TemplateListViewModel
{
    public double WidthHeight { get; set; }

    public ICommand LoadTemplates => new Command(MyHandler);
    public int CurrentTemplateCountReceived;
    public bool HitBottomOfList = false;
    public ObservableCollection<TemplateSource> sourceList { get; set; }


    public TemplateListViewModel()
    {
        CurrentTemplateCountReceived = 0;
        sourceList = new ObservableCollection<TemplateSource>();

        var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
        var width = mainDisplayInfo.Width;
        var density = mainDisplayInfo.Density;
        var ScaledWidth = width / density;

        WidthHeight = (ScaledWidth / 2);

        MyHandler();
    }

    private async Task LoadTemplateList()
    {
        if (HitBottomOfList == false)
        {
            List<Template> templateList = await App.RestService.GetTemplates(App.User, CurrentTemplateCountReceived);

            if (templateList != null)
            {
                foreach (var template in templateList)
                {
                    ImageSource source = ImageSource.FromUri(new Uri("mysite.org/myapp/" + template.FileName));
                    TemplateSource templateSource = new TemplateSource { Id = template.Id, Source = source, WidthHeight = WidthHeight, FileName = template.FileName };
                    sourceList.Add(templateSource);
                }

                CurrentTemplateCountReceived = sourceList.Count;
            }
            else
            {
                HitBottomOfList = true;
            }
        }
    }

    bool handling = false;

    public async void MyHandler()
    {
        // already handling an event, ignore the new one
        if (handling) return;

        handling = true;

        await LoadTemplateList();

        handling = false;
    }
}
0 голосов
/ 12 января 2020

Вам, вероятно, следует использовать Command с CanExecute с ChangeCanExecute, как указано здесь в документации

Также отмените подписку на события -= перед подпиской

И вы можете сделать команду asyn c и добавить ожидаемое действие как

Command MyCommand = new Command(async () => await ExecuteMyCommand());
...