C# Xamarin Forms:调试器离开异步方法而不等待
我刚开始使用XamarinForms,遇到了一个奇怪的问题 应用程序流程如下所示:C# Xamarin Forms:调试器离开异步方法而不等待,c#,xamarin,xamarin.forms,async-await,C#,Xamarin,Xamarin.forms,Async Await,我刚开始使用XamarinForms,遇到了一个奇怪的问题 应用程序流程如下所示: 从一个页面(NewExpensePage.cs)中,我打开一个用于创建操作的模式(push async) 页面具有带有ViewModel(ExpenseViewModel.cs)的BindingContext 按钮命令与ViewModel类中的命令(SaveExpenseCommand)连接,该命令将调用服务(IBTService.cs)中的方法,该服务将发出HttpPost请求 页面代码隐藏: public
- 从一个页面(NewExpensePage.cs)中,我打开一个用于创建操作的模式(push async)
- 页面具有带有ViewModel(ExpenseViewModel.cs)的BindingContext
- 按钮命令与ViewModel类中的命令(SaveExpenseCommand)连接,该命令将调用服务(IBTService.cs)中的方法,该服务将发出HttpPost请求
public partial class NewExpensePage : ContentPage
{
private readonly ExpenseViewModel viewModel;
public NewExpensePage(int currentGroupId)
{
InitializeComponent();
viewModel = new ExpenseViewModel(currentGroupId);
this.BindingContext = viewModel;
// let this page know save op has completed, and the close the modal
MessagingCenter.Subscribe<ExpenseViewModel>(this, "save-completed", async (i) => { await Navigation.PopModalAsync(); });
}
}
最后是服务代码中的方法(IBTService.cs):
公共异步任务SaveExpense(费用模型)
{
使用(var httpClient=new httpClient())
{
httpClient.BaseAddress=新Uri(api);
httpClient.DefaultRequestHeaders.Add(“Authorization”,$“Bearer{token}”);
var dbModel=新的API费用
{
金额=型号。金额,
日期=model.Date.ToString(“dd-MM-yyyy”,CultureInfo.InvariantCulture),
ExpenseCategoryId=型号.ExpenseCategoryId,
描述=模型。描述
};
//这里:调试器运行到调用者方法(回到视图模型中),而无需等待完成
var response=wait httpClient.PostAsync(“api/Expenses/PostExpense”,新的StringContent(JsonConvert.SerializeObject(dbModel));
if(响应。IsSuccessStatusCode)
{
返回true;//临时解决方案
}
返回false;
}
}
这里的问题始于最后一个代码部分中的var response=wait httpClient.PostAsync…
,调试器在执行这一行时立即跳出执行,而不是*等待此结果完成
任何帮助都将不胜感激 试试这个,
等待httpClient.PostAsync(“api/Expenses/postaexpense”,新的StringContent(JsonConvert.SerializeObject(dbModel),Encoding.UTF8,“application/json”)
您可能还想尝试将完整路径添加到PostAsync
…没有区别,我甚至尝试了另一个视图的工作get请求。api还可以。我可能在mvvm处理异步/等待的方式上误用了一些基本规则……它在方法SaveExpense中返回true还是false?Await不会阻止程序,它将在任务完成时继续执行。一旦它执行这一行,默认行为是返回到viewModel并执行其他代码,一旦响应返回,它将在这一行之后执行代码,然后返回true或false。@đxěŕ和Jack Hua you都是对的。问题似乎在于http调用,而不是体系结构。特别是因为我将该调用视为一个fire-and-forget情况,因为一旦发出http调用返回控件,我就关闭了pagemodal。我修改了代码以返回错误消息和响应状态,并删除了重定向部分,这是关于模型状态验证的部分,谢谢你们两位。谢谢你们的所有输入,帮助我完成了挑战
public class ExpenseViewModel : BaseViewModel
{
/* ... */
public Command SaveExpenseCommand { get; set; }
private readonly int CurrentGroupId;
public ExpenseViewModel(int selectedGroupId)
{
CurrentGroupId = selectedGroupId;
this.LoadCategoriesCommand = new Command(async () => await LoadCategories());
this.SaveExpenseCommand = new Command(async () => await SaveExpense());
}
async Task SaveExpense()
{
Item.ExpenseCategoryId = SelectedCategory.Id;
await IBTService.SaveExpense(Item);
MessagingCenter.Send(this, "save-completed");
}
}
public async Task<bool> SaveExpense(Expense model)
{
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(api);
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
var dbModel = new ApiExpense
{
Amount = model.Amount,
Date = model.Date.ToString("dd-MM-yyyy", CultureInfo.InvariantCulture),
ExpenseCategoryId = model.ExpenseCategoryId,
Description = model.Description
};
// HERE: Debugger runs out to caller method (back in view model) without waiting for this to complete
var response = await httpClient.PostAsync("api/Expenses/PostExpense", new StringContent(JsonConvert.SerializeObject(dbModel)));
if (response.IsSuccessStatusCode)
{
return true; //temp solution
}
return false;
}
}