C# 使用async await ContinueWith在主线程上运行然后调用?
下面的代码工作得很好。它在UI上显示微调器,使用线程池中的线程启动任务,并运行繁重的操作,一旦完成,逻辑将隐藏微调器在主线程上按预期执行C# 使用async await ContinueWith在主线程上运行然后调用?,c#,multithreading,asynchronous,xamarin.forms,C#,Multithreading,Asynchronous,Xamarin.forms,下面的代码工作得很好。它在UI上显示微调器,使用线程池中的线程启动任务,并运行繁重的操作,一旦完成,逻辑将隐藏微调器在主线程上按预期执行 public void LoadCustomers() { // Update UI to show spinner this.LoadingCustomers = true; Task.Run(async () => { v
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/configureWait选项编写此逻辑?使用这些选项似乎会阻塞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();
}
public异步任务GetCustomers()
{
return wait this.dbContext.Customers.toListSync();
}
更新
然而,FCin的答案是正确的;其根源似乎是EFCore和ToListSync,它不是异步运行的。编辑:@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
之后的代码在当前线程上执行,因此它应该是现成的。编写这种方法的正确方法是从头到尾使用async/await
。现在您正在执行fire,如果任务中出现异常,请忘记其含义。运行,您将永远不会知道它。您应该从事件处理程序开始。这可以是任何东西,鼠标点击,页面加载等
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。仅当您执行CPU限制的操作(例如计算PI的位数)时才运行。如何实现GetCustomers
?在返回任务之前,它可能处于阻塞状态。您还可以将LoadCustomers
设置为async Task
,从而避免显式使用ContinueWith
(或者async void
,如果您需要它作为特定类型的处理程序)什么框架?Asp.net?wpf?winforms?我已经用GetCustomers方法更新了这个问题,它是一个Xamarin Forms项目。如果GetCustomers
已经是一个async
支持任务
,为什么还要麻烦使用任务。运行,而不是直接等待它?编译器将自动将async
方法转换为一系列幕后延续。这正是async
/await
的设计初衷。[…]除非//代码中有某些东西为了清晰起见被截断了
,需要另一个线程。如果只是“正常”代码,我强烈建议直接等待;您根本不必担心跨线程封送。如果this.custService.GetCustomers()
已经是一个异步
支持任务
,为什么要使用任务运行
,我甚至没有检查代码的内容,而是直接等待它:D让我来解决这个问题。您需要将异步添加到事件处理程序签名中。