三、WinUI3中在OnLauncher处理单例
2022/8/8 6:24:14
本文主要是介绍三、WinUI3中在OnLauncher处理单例,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
今天写程序中比较重要的一个知识点单例;他是软件生命周期中的第一步,如何启动;因为在传统开发中涉及到进程间通信;启动时间优化;逻辑拆分解耦,等等。这一步很重要,WinUI3对这一步做了什么一的优化和封装,我们先看单例;
在 Application.OnLaunched 中完成此工作可以简化应用。 不过,这在很大程度上取决于应用所执行的其他操作。 如果打算结束重定向,然后终止当前实例,则需要避免执行任何一次性工作(甚至是需要显式撤消的工作)。 在这类情况下,Application.OnLaunched 可能太晚,你可能更希望在应用的 Main 或 wWinMain 函数中完成此工作。这一篇只分析OnLaunched单例的使用,在Main和wWinMain做单例涉及的知识更多,对初学者不是很友好,可以先跳过,感兴趣的可以看示例
Main单例连接
看Onlaunched文档示例;
对照文档:
https://docs.microsoft.com/zh-cn/windows/apps/windows-app-sdk/migrate-to-windows-app-sdk/guides/applifecycle#single-instancing-in-main-or-wwinmain
单例的位置主要是Main或者wWinMain函数和Application.OnLaunched;针对于情况的不同,使用的函数也不一样,我们开始学习这一块OnLaunched代码:
using Microsoft.UI.Xaml; using System; using System.Diagnostics; // To learn more about WinUI, the WinUI project structure, // and more about our project templates, see: http://aka.ms/winui-project-info. namespace AppInstances { /// <summary> /// Provides application-specific behavior to supplement the default Application class. /// </summary> public partial class App : Application { /// <summary> /// Initializes the singleton application object. This is the first line of authored code /// executed, and as such is the logical equivalent of main() or WinMain(). /// </summary> public App() { this.InitializeComponent(); } /// <summary> /// Invoked when the application is launched normally by the end user. Other entry points /// will be used such as when the application is launched to open a specific file. /// </summary> /// <param name="args">Details about the launch request and process.</param> protected override async void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) { // If this is the first instance launched, then register it as the "main" instance. // If this isn't the first instance launched, then "main" will already be registered, // so retrieve it. var mainInstance = Microsoft.Windows.AppLifecycle.AppInstance.FindOrRegisterForKey("Main"); if (!mainInstance.IsCurrent) { //Redirect the activation (and args) to the "main" instance, and exit. var activatedEventArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs(); await mainInstance.RedirectActivationToAsync(activatedEventArgs); Process.GetCurrentProcess().Kill(); return; } m_window = new MainWindow(); m_window.Activate(); } private Window m_window; } }
主要看Override OnLauncher方法;
我们看OnLauncher的方法描述:
翻译后是当这个APP被终端用户正常的启动的时候,这个方法被调用,由其他方式被启动例如打开一个文件时,也会被调用;
启动参数是有关启动请求和流程的详细信息;
最为关键的是这个
var mainInstance = Microsoft.Windows.AppLifecycle.AppInstance.FindOrRegisterForKey("Main");
如果这是第一个启动的实例,则将其注册为“Main”实例。如果这不是第一个启动的实例,那么“main”将已经注册,因此请检索它。
我翻了一下文档
FindorRegisterForKey("")方法的描述是:
向平台注册应用实例,如果另一个实例已注册此密钥,则查找现有实例
参数为作为实例键的非空字符串;
返回AppInstance
一个应用实例,表示注册密钥的第一个应用。调用方可以确定该实例是否为当前实例。
同时请注意
应用注册平台后,当其他实例查询应用实例时,将返回该应用。一个应用实例可以使用不同的密钥注册多次。系统缓存为每个实例维护一行,因此,密钥将被覆盖。
我们做以下2个验证:
- 启动多个AppInstances 实例,添加部分代码观察返回结果;
- 我们继续创建一个AppInstances2实例,同时复制一样的OnLauncher代码,我们验证一下FindorRegisterForKey能否跨应用;观察返回结果;
为了更好的观察,我们添加文件类型关联实例,结合AppInstances,看返回结果;
步骤:
打开 Package.appxmanifest。 在“声明”中,选择“文件类型关联”,然后单击“添加”。 设置以下属性:
显示名称:MyFile 名称:myfile 文件类型:.myf
我多添加了一个文件类型: .pdf
若要注册文件类型关联,请生成应用,进行启动,然后关闭。
using Microsoft.UI.Xaml; using System; using System.Diagnostics; using Windows.ApplicationModel.Activation; using System.Linq; // To learn more about WinUI, the WinUI project structure, // and more about our project templates, see: http://aka.ms/winui-project-info. namespace AppInstances { /// <summary> /// Provides application-specific behavior to supplement the default Application class. /// </summary> public partial class App : Application { /// <summary> /// Initializes the singleton application object. This is the first line of authored code /// executed, and as such is the logical equivalent of main() or WinMain(). /// </summary> public App() { this.InitializeComponent(); } /// <summary> /// Invoked when the application is launched normally by the end user. Other entry points /// will be used such as when the application is launched to open a specific file. /// </summary> /// <param name="args">Details about the launch request and process.</param> protected override async void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) { // If this is the first instance launched, then register it as the "main" instance. // If this isn't the first instance launched, then "main" will already be registered, // so retrieve it. var mainInstance = Microsoft.Windows.AppLifecycle.AppInstance.FindOrRegisterForKey("Main"); if (!mainInstance.IsCurrent) { //Redirect the activation (and args) to the "main" instance, and exit. var activatedEventArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs(); await mainInstance.RedirectActivationToAsync(activatedEventArgs); Process.GetCurrentProcess().Kill(); return; } else { mainInstance.Activated += MainInstance_Activated; } m_window = new MainWindow(); m_window.Activate(); } private void MainInstance_Activated(object sender, Microsoft.Windows.AppLifecycle.AppActivationArguments e) { if (e.Kind == Microsoft.Windows.AppLifecycle.ExtendedActivationKind.File) { var fileActivated = (FileActivatedEventArgs)e.Data; var file = fileActivated.Files.FirstOrDefault(); } } private Window m_window; } }
我们在主Main中注册了Activated的消息,如果有程序启动则触发单实例的Action回调给主进程,通过前面的步骤我们注册了*.pdf
我在右键使用AppInstances打开PDF后,监听到file的Path就是我打开的pdf所以单实例这里整体流程就通了;
FindOrRegisterForKey注册多个不同名称我就不验证了,基本没有这种需求;
我需要验证以下跨不同进程的FindOrRegisterForKey是否生效;
方便调试修改代码发送内容到输出中:
private void MainInstance_Activated(object sender, Microsoft.Windows.AppLifecycle.AppActivationArguments e) { if (e.Kind == Microsoft.Windows.AppLifecycle.ExtendedActivationKind.File) { var fileActivated = (FileActivatedEventArgs)e.Data; var file = fileActivated.Files.FirstOrDefault(); Debug.WriteLine(file.Path); } }
2个完全一样的工程,使用一样的FindOrRegisterForKey,最后得出结论互不影响。
同时AppInstance还支持其他方法:
- GetActivatedEventArgs()
- GetCurrent()
- GetInstances()
- RedirectActivationToAsync(AppActivationArguments)
- Restart(String)
- UnregisterKey()
1 2 3 4 我们都验证了。剩下的有需求的小伙伴自己验证把。
这篇到此就结束拉。单例还有很多。但是目前对我来说已经够用了,后续性能优化部分会在分析其他单例模式;
欢迎来群542633085 一起学习WinUI3
这篇关于三、WinUI3中在OnLauncher处理单例的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-04-26高性能表格工具VTable总体构成-icode9专业技术文章分享
- 2024-04-16软路由代理问题, tg 无法代理问题-icode9专业技术文章分享
- 2024-04-16程序猿用什么锅-icode9专业技术文章分享
- 2024-04-16自建 NAS 的方案-icode9专业技术文章分享
- 2024-04-14ansible 在远程主机上执行脚本,并传入参数-icode9专业技术文章分享
- 2024-04-14ansible 在远程主机上执行脚本,并传入参数, 加上remote_src: yes 配置-icode9专业技术文章分享
- 2024-04-14ansible 检测远程主机的8080端口,如果关闭,则echo 进程已关闭-icode9专业技术文章分享
- 2024-04-14result 成功怎么写-icode9专业技术文章分享
- 2024-04-14stopped 状态设置为变量,由外部传递进来-icode9专业技术文章分享
- 2024-04-14为什么ansible执行远程脚本需要放到后台-icode9专业技术文章分享