【发布时间】:2018-09-14 11:11:44
【问题描述】:
以下代码完美运行。它在 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;
});
}
根据 cmets 的要求,这里是 GetCustomers 的代码。 dbContext 是 EntityFrameworkCore。
public async Task<List<CustomerModel>> GetCustomers()
{
return await this.dbContext.Customers.ToListAsync();
}
更新
但是,FCin 的答案是正确的;原因似乎是 EFCore 和 ToListAsync,它没有异步运行。
【问题讨论】:
-
GetCustomers是如何实现的?它可能在返回Task之前被阻塞。您还可以将LoadCustomers设为async Task,从而避免必须显式使用ContinueWith(或async void,如果您需要它作为特定类型的处理程序) -
什么框架? ASP.NET? wpf? winform?
-
我已经用 GetCustomers 方法更新了问题,它是一个 Xamarin Forms 项目
-
如果
GetCustomers已经是支持Task的async,为什么还要使用Task.Run,而不是直接等待它呢?编译器会自动将您的async方法转换为幕后的一系列延续。这正是async/await的设计目的。 -
[...]除非
// code truncated for clarity中有需要不同线程的内容。如果只是“普通”代码,我强烈建议直接等待;您根本不必担心跨线程编组。
标签: c# multithreading asynchronous xamarin.forms