代码之家  ›  专栏  ›  技术社区  ›  Noobie3001

使用async wait continuewith在主线程替代项上运行然后调用?

  •  1
  • Noobie3001  · 技术社区  · 7 年前

    以下代码工作正常。它在UI上显示微调器,使用线程池中的线程启动任务,并在完成后运行重型操作,以隐藏微调器按预期在主线程上执行的逻辑。

        public void LoadCustomers()
        {
            // Update UI to show spinner
            this.LoadingCustomers = true;
    
            Task.Run(async () =>            
            {
                var customers = await this.custService.GetCustomers();
                // code truncated for clarity
    
                Device.BeginInvokeOnMainThread(() => 
                {
                    // Update UI to hide spinner
                    this.LoadingCustomers = false;
                });
            });
        }
    

    我的问题是:有没有更好的方法可以使用continuewith/configureAwait选项来编写这个逻辑?使用这些选项似乎会阻塞UI线程。在下面的示例中,UI线程是否应该继续运行UI逻辑(动画微调器/用户输入),然后返回以完成ContinueWith中的逻辑?

        public void LoadCustomers()
        {
            // Update UI to show spinner
            this.LoadingCustomers = true;
    
            this.custService.GetCustomers().ContinueWith((t) =>
            {
                var customers = t.Result;
                // code truncated for clarity
    
                // Update UI to hide spinner
                this.LoadingCustomers = false;
            });
        }
    

    根据注释中的要求,这里是getCustomers的代码。dbContext是EntityFrameworkCore。

        public async Task<List<CustomerModel>> GetCustomers()
        {
            return await this.dbContext.Customers.ToListAsync();
        }
    

    更新

    然而,fcin的答案是正确的;原因根源似乎是efcore和tolistasync,它没有异步运行。

    2 回复  |  直到 7 年前
        1
  •  5
  •   FCin    7 年前

    正确的写作方法是 async/await 从头到尾。现在你在开火,如果里面有例外的话,你就忘记了它的意义。 Task.Run 你永远不会知道。您应该从事件处理程序开始。这可以是任何内容,鼠标单击,页面加载等。

    private async void MouseEvent_Click(object sender, EventArgs args)
    {
        await LoadCustomers();
    }
    
    public async Task LoadCustomers()
    {
        // Update UI to show spinner
        this.LoadingCustomers = true;
    
        // We don't need Device.BeginInvokeOnMainThread, because await automatically 
        // goes back to calling thread when it is finished
        var customers = await this.custService.GetCustomers();
    
        this.LoadingCustomers = false;
    }
    

    有一种简单的方法可以记住何时使用 任务运行 . 使用 任务运行 只有 当你做一些CPU限制的事情时,比如计算pi的位数。

        2
  •  0
  •   Toni Petrina    7 年前

    编辑:@bradley uffner建议只写以下内容:

    public async Task LoadCustomers()
    {
        // Update UI to show spinner
        this.LoadingCustomers = true;
    
        var customers = await this.custService.GetCustomers();
        // code truncated for clarity
    
        // you are still on UI thread here
        this.LoadingCustomers = false;
    }
    

    这个怎么样?

    public async Task LoadCustomers()
    {
        // Update UI to show spinner
        this.LoadingCustomers = true;
    
        await Task.Run(async () =>            
        {
            var customers = await this.custService.GetCustomers();
            // code truncated for clarity
        });
    
        this.LoadingCustomers = false;
    }
    

    后码 await 是在当前线程上执行的,因此它应该是开箱即用的。