c# - Task.Run 然后使用异步等待 ContinueWith 在主线程替代上调用?
问题描述
以下代码完美运行。它在 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 有关,它不是异步运行的。
解决方案
编写这种方法的正确方法是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;
}
有一种简单的方法可以记住何时使用Task.Run
. Task.Run
仅在您执行 CPU 限制的操作时使用,例如计算 PI 的位数。
推荐阅读
- javascript - 将实时时钟时间链接到视频播放器时间
- vim - 在 neovim 和 MacVim 上使用 SpaceVim,无法获取插件脚本的位置
- selenium-webdriver - 如何在并行执行时杀死 IEDriverServer?
- php - 如何防止php中的自动注销会话?
- php - Silverstripe 核心从 3.5.6 升级到 3.6.6
- oracle - Oracle SQL Developer 连接问题
- c++ - 节点 FFi 访问 CTAPI
- java - 无法在迭代器中引用以前使用的元素(java)
- jquery - 在 jQuery datepicker 中选择为 null 的日期
- javascript - javascript对onclick事件的奇怪动作