UWP应用连接串口后两次导航至MainPage无响应问题如何解决?
问题1:Page_Loaded事件是否会在每次页面重载时触发?
是的,UWP中Page_Loaded事件会在每次页面被加入到视觉树时触发,包括首次加载、导航回该页面、页面被重新渲染等场景,没有内置的仅首次加载触发的系统事件,你可以通过自定义标记位实现仅首次执行初始化逻辑。
问题2:故障根因
你遇到的串口占用问题核心原因有两个:
- 页面导航默认会创建新的页面对象实例,原页面持有的串口、读任务、
DataReader等资源没有被正确释放,一直占用COM口 setupCOM中的while(true)死循环没有取消逻辑,导航走之后读任务还在后台持续运行,进一步占用资源
推荐解决方案
方案1:串口全局复用(更稳定,推荐优先使用)
把串口连接、监听逻辑从页面中剥离,放到App.xaml.cs中作为全局静态资源,整个应用生命周期仅初始化一次串口连接,页面只需要订阅串口数据接收事件即可,完全避免重复连接问题:
- 在
App.xaml.cs中定义全局的串口对象、数据接收事件 - 应用启动时初始化一次串口连接、启动监听
- MainPage加载时订阅串口数据接收事件,导航走时取消订阅即可,不需要操作串口的连接/释放
方案2:开启页面缓存
如果不想改全局逻辑,可以直接给MainPage开启导航缓存,Frame只会创建一次MainPage实例,不会重复触发初始化逻辑:
在MainPage的构造函数中加入:
this.NavigationCacheMode = NavigationCacheMode.Required;
同时可以加一个首次加载标记位,避免重复执行初始化:
private bool _isFirstInit = true; private async void Page_Loaded(object sender, RoutedEventArgs e) { if (_isFirstInit) { _isFirstInit = false; await setupCOM(); } }
方案3:页面离开时释放资源
如果需要每次离开页面都释放串口,需要重写OnNavigatingFrom方法按顺序释放资源,避免抛出异常:
protected override async void OnNavigatingFrom(NavigatingCancelEventArgs e) { base.OnNavigatingFrom(e); // 1. 先取消读任务 if (ReadCancellationTokenSource != null && !ReadCancellationTokenSource.IsCancellationRequested) { ReadCancellationTokenSource.Cancel(); await Task.Delay(100); ReadCancellationTokenSource.Dispose(); ReadCancellationTokenSource = null; } // 2. 释放DataReader if (dataReaderObject != null) { dataReaderObject.Dispose(); dataReaderObject = null; } // 3. 释放串口对象 if (serialPort != null) // 替换为你实际持有的SerialDevice对象变量名 { serialPort.Dispose(); serialPort = null; } }
同时需要在ReadAsync方法中处理取消异常,避免未捕获异常导致应用崩溃:
private async Task ReadAsync(CancellationToken cancellationToken) { try { // 原有逻辑不变 } catch (OperationCanceledException) { // 任务取消属于正常操作,不抛异常 } catch (Exception ex) { // 其他异常按需处理 Debug.WriteLine(ex.Message); } }
内容的提问来源于stack exchange,提问作者Andrew Taylor
相关产品推荐
相关产品推荐

