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

问题描述 投票:0回答:2

我有问题。我为我的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将立即设置为false

现在如何等待LoadTemplateList()

c# xamarin xamarin.forms xamarin.android xamarin.ios
2个回答
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;
    }
}

0
投票

您可能应该将CommandCanExecute结合使用,如ChangeCanExecute中所述]

也需要在订阅前通过documentation退订事件

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

-=

-1
投票

只需这样做

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

var myTask = LoadTemplateList(); Task.WaitAll(myTask); // This is blocking -

© www.soinside.com 2019 - 2024. All rights reserved.