我正在尝试等待任务结束。此任务从服务器加载一系列内容,通常需要2到3秒。此任务由命令LoadItemsCommand启动。任务结束后,它应该检查是否加载了任何内容,以及加载的项目是否已经包含值。如果是,它应该从工具栏中删除一个按钮。
但它没有等待。命令调用并特别要求等待任务,但在主页面上,事情没有等待任务结束就继续进行。我试图放置一个30秒等待时间的循环来等待命令工作,但没有任何效果。
下面是视图模型中的命令:
LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand());
下面是ViewModel中的LoadItems函数
async Task ExecuteLoadItemsCommand()
{
if (IsBusy)
return;
IsBusy = true;
List<string> stockIds = new List<string>();
foreach (var orderline in this._order)
{
stockIds.Add(orderline.StockId);
}
string[] array = new string[stockIds.Count];
stockIds.CopyTo(array, 0);
this._products = await Common.GetProducts(new ProductSearchFilter { StockId = array });
_scanStart = Common.Now;
Items.Clear();
bool already_scanned = false; // Todo trouver un meilleur non car pas tres explicite
foreach (PickingOrderLineToHandle orderLine in _order)
{
if (orderLine.ScannedQuantity < orderLine.Quantity)
{
if ((bool)orderLine.WasSentToEnd && !already_scanned)
{
Items.Add(new ListItem() { Name = " ----- ", Id = "-1" });
already_scanned = true;
}
Product product = null;
foreach (var prod in _products)
{
if (prod.StockId == orderLine.StockId)
{
product = prod;
break;
}
}
Items.Add(new ListItem() { Name = $"{(orderLine.Quantity - orderLine.ScannedQuantity).ToString()} / {orderLine.Quantity}\t + {orderLine.Table_bin.LabelAddress} {product.ProductName} {orderLine.stock.Platform}", Id = orderLine.StockId });
}
}
IsBusy = false;
}
下面是页面中的调用:
protected override void OnAppearing()
{
base.OnAppearing();
viewModel.LoadItemsCommand.Execute(null);
int loop = 0;
while (viewModel.IsBusy && loop < 60)
{
System.Threading.Thread.Sleep(500);
loop++;
};
if (loop == 60)
{
DisplayAlert("Erreur", "Une erreur est survenue lors du chargment. Veuillez réessayer.", "Ok");
Navigation.PopAsync();
}
var cantCancel = viewModel.Items.Any(i => i.BookedQuantity > 0);
if (Common.IsTeamLeader)
cantCancel = false;
if (cantCancel)
{
var cancelButton = this.ToolbarItems.Where(b => b.Text == "Annuler").First();
this.ToolbarItems.Remove(cancelButton);
}
}
1条答案
按热度按时间thigvfpy1#
问题
下面的语句看起来像是一个阻塞调用,但实际上,由于
Command
调用的方法是一个异步匿名函数,它将以*触发并忘记*的方式执行,并且不会等待:这是因为命令是如何定义的:
这样的
Command
总是同步执行的,但是,当从同步上下文调用async void
方法时,它只会开始执行,而不会执行await
方法(因此 * 触发并忘记 *)。溶液
现在,你使用
Command
的方式是不寻常的。通常,你会从UI控件绑定到Command
,或者你只是触发它的执行。你希望它在***之前完成***其余的代码执行,这不是我上面解释的情况。您可以执行以下操作,而不是像这样执行命令:
1.确保
ExecuteLoadItemsCommand()
正在返回Task
1.将
ExecuteLoadItemsCommand()
的可见性更改为public1.将名称更改为
ExecuteLoadItemsAsync()
,这是返回异步任务的方法的常用表示法您的新方法签名应该如下所示:
然后,在页面的代码隐藏中,您可以将
async
方法重写更改为异步运行,方法是将async
关键字添加到签名中,然后等待ExecuteLoadItemsAsync()
方法:这样,您就可以直接执行并等待该方法,
Command
仍然可以用于绑定任何UI元素,例如按钮。可选改进
在ViewModel中,可以使用
AsyncRelayCommand
代替Command
,如下所示:然而,这并不能改变这样一个事实,即您不应该在页面代码中以您一直尝试的方式执行Command。