【问题标题】:How to wait on task that runs async method如何等待运行异步方法的任务
【发布时间】:2018-06-22 08:55:00
【问题描述】:

我正在编写 WPF 应用程序,最近开始使用 await/async,因此 GUI 线程不会执行任何耗时的操作。

我的问题是我想使用实体框架从 db 异步加载两个集合。我知道我不能在 DbContext 上调用两个 ToListAsync() 方法,所以我想使用任务。

我编写了异步方法LoadData(),它应该等待完成LoadNotifications(),然后调用LoadCustomers()

但是当执行到await this.context.MailingDeliveryNotifications.ToListAsync(); 时,它会创建另一个任务,并且不知何故它不关心我的LoadData() 方法中的task.Wait(),因此它在完成对DbContext 的第一次调用之前调用LoadCustomers()

代码:

    public async void LoadData()
    {
        Task task = this.LoadNotifications();
        task.Wait();
        await this.LoadCustomers();
    }

    private Task LoadNotifications()
    {
        return Task.Run(() => this.LoadNotificationsAsync());
    }

    private async void LoadNotificationsAsync()
    {
        List<MailingDeliveryNotification> res = await this.context.MailingDeliveryNotifications.ToListAsync();
        this.Notifications = new ObservableCollection<MailingDeliveryNotification>(res);
    }

    private Task LoadCustomers()
    {
        return Task.Run(() => this.LoadNotificationsAsync());
    }

    private async void LoadCustomersAsync()
    {
        List<Customer> res = await this.context.Customers.ToListAsync();
        this.Customers = new ObservableCollection<Customer>(res);
    }

我知道我可以使用此代码解决此问题

    public async void LoadData()
    {
        List<MailingDeliveryNotification> res = await this.context.MailingDeliveryNotifications.ToListAsync();
        this.Notifications = new ObservableCollection<MailingDeliveryNotification>(res);

        List<Customer> res2 = await this.context.Customers.ToListAsync();
        this.Customers = new ObservableCollection<Customer>(res2);
    }

但是当我需要添加另一个集合以从 db 加载时,这种方法会增长很多。我想保持我的代码干净。

【问题讨论】:

  • 另外,async void 方法很淘气。
  • 不要使用 Task.Run 只是为了调用异步方法。不需要,该方法已经返回一个任务并且它已经在后台运行。
  • 除了事件处理程序外,不要使用async void。你不能等待他们,期间。 async void LoadNotificationsAsync()async void LoadData 都不能等待。

标签: c# wpf entity-framework nested async-await


【解决方案1】:

简化您的代码:

public async Task LoadDataAsync()
{
    await LoadNotificationsAsync();
    await LoadCustomersAsync();
}

private async Task LoadNotificationsAsync()
{
    var res = await context.MailingDeliveryNotifications.ToListAsync();
    Notifications = new ObservableCollection<MailingDeliveryNotification>(res);
}

private async Task LoadCustomersAsync()
{
    var res = await context.Customers.ToListAsync();
    Customers = new ObservableCollection<Customer>(res);
}

或者可能只是:

public async Task LoadDataAsync()
{
    Notifications = new ObservableCollection<MailingDeliveryNotification>(
        await context.MailingDeliveryNotifications.ToListAsync());

    Customers = new ObservableCollection<Customer>(
        await context.Customers.ToListAsync());
}

【讨论】:

  • 完美运行,谢谢。但它是如何工作的?当 LoadNotifications 重新调用 Task 时,是返回执行整个方法的 Task 还是来自 context.MailDeliveryNotifications.ToListAsync() 调用的 Task?
猜你喜欢
  • 2019-05-07
  • 1970-01-01
  • 1970-01-01
  • 2012-11-15
  • 2020-04-24
  • 1970-01-01
  • 1970-01-01
  • 2018-02-23
  • 1970-01-01
相关资源
最近更新 更多