C#等待异步方法完成,然后继续

时间:2020-01-12 00:06:45

标签: c# xamarin xamarin.forms xamarin.android xamarin.ios

我有问题。我为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。现在,我还在xaml中创建了一个RemainingItemsThresholdReachedCommand="{Binding LoadTemplates}",因此当它到达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将被设置为{{1} }!

现在如何等待false

2 个答案:

答案 0 :(得分:1)

现在如何等待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;
    }
}

答案 1 :(得分:0)

您可能应该将CommandCanExecuteChangeCanExecute一起使用,如documentation

中所述

在订阅之前,-=还取消订阅事件

您可以使命令异步,并添加等待的操作

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