Xamarin.Forms异步调用MainPage.test()获取控件值始终为0问题
错误原因
核心问题是你在异步方法中调用test()时,操作的是一个全新创建、未实际加载显示的MainPage实例,而非用户正在交互的那个页面实例:
- App启动时在构造函数中创建了一个MainPage实例赋值给应用主页面,这个实例挂载在可视化树上,用户操作摇杆时会更新其上JoystickControl的Xposition值,按钮点击调用的就是这个实例的test()方法,因此能拿到正确数值。
- 你在Bth类的loop方法中写了
var mainPage = new Views.MainPage();,这行代码会生成一个独立的MainPage对象:这个对象从未被导航到页面栈、从未完成渲染加载、也没有接收过任何用户的摇杆操作,其上的JoystickControl所有属性都停留在初始默认值,Xposition自然始终为0。 - 代码还有一处不规范的点:异步循环中使用
Thread.Sleep(5000)会阻塞执行线程,异步场景下应该使用非阻塞的await Task.Delay()。
修复方法
- 移除异步代码中新建MainPage实例的逻辑,直接获取应用当前正在显示的主页面实例调用方法:
private async Task loop(string name, int sleepTime, bool readAsCharArray) { while (true) { MainThread.BeginInvokeOnMainThread(() => { // 直接获取当前运行的真实MainPage实例,禁止new新页面 if (Application.Current.MainPage is Views.MainPage mainPage) { mainPage.test(); } }); // 替换阻塞休眠为异步等待 await Task.Delay(5000); } }
- 长期维护建议:不要让蓝牙业务类直接依赖UI页面实例,耦合度过高。可以将摇杆位置这类需要跨类访问的状态抽离到独立的状态管理类中,UI操作时更新状态类的属性值,蓝牙逻辑直接读取状态类属性即可,后续调整UI结构时不会影响蓝牙逻辑。
内容的提问来源于stack exchange,提问作者Jakob Ofner
相关产品推荐
相关产品推荐

