在Visual Studio 2017的Xamarin Forms项目中实现线程内异步方法
解决Xamarin Forms线程内调用异步UI方法的问题
首先得指出你当前代码里的几个关键问题:
DisplayAlert是UI操作,必须在主线程执行,你现在在手动创建的后台线程里直接调用它,会立刻抛出InvalidOperationException,因为后台线程无权访问UI元素。- 在线程里使用
async void方法(ShowWarning)是个坏实践——除了UI事件处理程序外,async void无法被等待,抛出的异常也很难捕获,会导致程序不稳定。
下面给你两种正确的实现方式,根据你的实际需求选择:
方式一:优先使用async/await(推荐)
如果你的需求是先执行一些后台逻辑,再弹出警告框,完全不需要手动创建Thread,用Task.Run处理后台任务,再自然回到主线程执行UI操作即可:
public async void btnAction_Click(object sender, System.EventArgs e) { // 执行后台耗时操作(比如数据加载、计算等) await Task.Run(() => { // 这里写你的后台逻辑,注意:不能操作UI // 比如模拟耗时操作:Thread.Sleep(2000); }); // 此时已经回到主线程,直接调用DisplayAlert bool response = await DisplayAlert("Warning", "Please Enter The Key", "Yes", "No"); // 根据用户选择做后续处理 if (response) { // 用户点击了Yes } else { // 用户点击了No } }
如果想把警告框的逻辑封装成独立方法,记得用async Task代替async void:
private async Task ShowWarningAsync() { bool response = await DisplayAlert("Warning", "Please Enter The Key", "Yes", "No"); // 这里处理用户的选择 } // 点击事件里调用 public async void btnAction_Click(object sender, System.EventArgs e) { await Task.Run(() => { // 后台操作 }); await ShowWarningAsync(); }
方式二:必须使用Thread的场景(不推荐)
如果因为某些特殊原因必须手动管理线程,那一定要在调用UI方法前切换回主线程,用Device.BeginInvokeOnMainThread实现:
public void btnAction_Click(object sender, System.EventArgs e) { var load = new System.Threading.Thread(async () => { // 这里执行后台逻辑 // ... // 切换到主线程执行UI操作 Device.BeginInvokeOnMainThread(async () => { bool response = await DisplayAlert("Warning", "Please Enter The Key", "Yes", "No"); // 处理用户选择 }); }); load.Start(btnText); }
关键注意事项
- 永远不要在后台线程直接操作UI元素,所有UI相关的调用都必须放在主线程。
- 尽量避免手动创建
Thread,Xamarin.Forms推荐用async/await+Task.Run的模式处理异步任务,代码更简洁且更容易维护。 - 非UI事件处理程序中,坚决不要用
async void,改用async Task,这样可以正确处理异常和等待逻辑。
内容的提问来源于stack exchange,提问作者charitht99 perera
相关产品推荐
相关产品推荐

