UWP项目调用Xamarin.Forms Device.StartTimer报错:需先调用Forms.Init()
一、解决"You must call Xamarin.Forms.Forms.Init();"错误
你在纯UWP项目里用了Xamarin.Forms的Device.StartTimerAPI,但没初始化Xamarin.Forms框架,导致了这个错误,按以下步骤修复:
1. 正确添加初始化代码
打开UWP项目的App.xaml.cs,找到OnLaunched方法,加入Xamarin.Forms的初始化逻辑:
protected override void OnLaunched(LaunchActivatedEventArgs e) { // 保留原有启动代码 Frame rootFrame = Window.Current.Content as Frame; if (rootFrame == null) { rootFrame = new Frame(); rootFrame.NavigationFailed += OnNavigationFailed; Window.Current.Content = rootFrame; } // 新增:初始化Xamarin.Forms,参数直接传方法里的e Xamarin.Forms.Forms.Init(e); if (e.PrelaunchActivated == false) { if (rootFrame.Content == null) { rootFrame.Navigate(typeof(MainPage), e.Arguments); } Window.Current.Activate(); } }
注意:这段初始化代码必须在你调用任何Xamarin.Forms API(比如Device.StartTimer、DependencyService)之前执行。
2. 错误原理
Device.StartTimer是Xamarin.Forms提供的跨平台定时器,它依赖Xamarin.Forms底层的平台调度器、生命周期管理等核心服务。你之前的Xamarin.Forms项目里,模板已经自动在平台项目(比如UWP的App.xaml.cs)里加了初始化代码,而新建的纯UWP项目没有,所以直接调用这些API会触发未初始化的异常。
另外,你代码里的DependencyService.Register<MainPage>()完全没必要——DependencyService是用来注册接口实现的,页面类不需要注册,直接删掉就行。
二、SkiaSharp动效的更好实现方式
用Device.StartTimer属于跨平台方案,但在纯UWP项目里,有更贴合原生、性能更好的替代方案:
1. 使用UWP原生DispatcherTimer
直接利用UWP系统的调度器,不需要依赖Xamarin.Forms:
private DispatcherTimer _animTimer; public MainPage() { InitializeComponent(); // 初始化定时器 _animTimer = new DispatcherTimer(); // 建议改成16ms(约60帧/秒),1ms刷新率太高会浪费CPU _animTimer.Interval = TimeSpan.FromMilliseconds(16); _animTimer.Tick += (sender, e) => canvasView.Invalidate(); _animTimer.Start(); // 其他初始化代码... }
记得引入Windows.UI.Xaml命名空间,还要绑定页面生命周期避免内存泄漏:
protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); _animTimer?.Start(); } protected override void OnNavigatedFrom(NavigationEventArgs e) { base.OnNavigatedFrom(e); _animTimer?.Stop(); }
2. 刷新率优化提示
你设置的1ms刷新率完全没必要——人眼最多识别60帧/秒(约16ms每帧),过高的刷新率会徒增CPU消耗,建议改成TimeSpan.FromMilliseconds(16),或者根据动画流畅度需求调整到10-30ms区间。
内容的提问来源于stack exchange,提问作者JonTheBrownDog

