Xamarin.Forms – BeginInvokeOnMainThread用于异步操作

我熟悉使用Device.BeginInvokeOnMainThread更新UI线程上的UI元素的规则,但是我有一个需要在实际上是Task的UI线程上运行的操作。

例如,XLabs.Forms.Mvvm上的Push / PopAsync方法似乎在iOS上表现不正确,除非在UI线程上调用它们。 Acr.UserDialogs库中还有另一个用于显示toasts等的示例。

我知道创建一个Action异步基本上是创建一个异步void lambda,并且在exception的情况下冒着创建死锁的风险,显然我不希望这种情况发生。

有没有人在UI线程上执行异步操作的解决方法,不涉及将Action标记为异步?

只要确保你在Action中处理exception,你应该没问题。 当您处理exception时,会出现您所描述的问题。 下面是从主线程运行异步方法的一个非常简单的示例。

private void Test() { Device.BeginInvokeOnMainThread(SomeMethod); } private async void SomeMethod() { try { await SomeAsyncMethod(); } catch (Exception e) // handle whatever exceptions you expect { //Handle exceptions } } private async Task SomeAsyncMethod() { await Navigation.PushModalAsync(new ContentPage()); } 

如果有人想要等待必须在主线程上执行的操作的结束,请将此删除

 public static class DeviceHelper { public static Task RunOnMainThreadAsync(Action action) { var tcs = new TaskCompletionSource(); Device.BeginInvokeOnMainThread( () => { try { action(); tcs.SetResult(null); } catch (Exception e) { tcs.SetException(e); } }); return tcs.Task; } public static Task RunOnMainThreadAsync(Task action) { var tcs = new TaskCompletionSource(); Device.BeginInvokeOnMainThread( async () => { try { await action; tcs.SetResult(null); } catch (Exception e) { tcs.SetException(e); } }); return tcs.Task; } }