From 53e19ecb1d38b04f2b36ba00b0f39417697279e5 Mon Sep 17 00:00:00 2001
From: 2dust <31833384+2dust@users.noreply.github.com>
Date: Tue, 8 Oct 2024 13:47:13 +0800
Subject: [PATCH] Improved Action Invoke

---
 v2rayN/ServiceLib/Common/Utils.cs             |  23 +---
 v2rayN/ServiceLib/Handler/ClashApiHandler.cs  |  24 ++--
 v2rayN/ServiceLib/Handler/CoreHandler.cs      |   8 +-
 .../ServiceLib/Handler/StatisticsHandler.cs   |   8 +-
 v2rayN/ServiceLib/Handler/TaskHandler.cs      |  14 +--
 v2rayN/ServiceLib/ServiceLib.csproj           |   4 +-
 v2rayN/ServiceLib/Services/DownloadService.cs |  10 +-
 .../ServiceLib/Services/SpeedtestService.cs   |   8 +-
 .../Statistics/StatisticsSingboxService.cs    |   8 +-
 .../Statistics/StatisticsV2rayService.cs      |   8 +-
 v2rayN/ServiceLib/Services/UpdateService.cs   | 106 +++++++++---------
 .../ViewModels/CheckUpdateViewModel.cs        |   2 +-
 .../ViewModels/DNSSettingViewModel.cs         |   6 +-
 .../v2rayN.Desktop/Views/MainWindow.axaml.cs  |   4 +-
 v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj   |   2 +-
 .../ViewModels/ThemeSettingViewModel.cs       |   4 +-
 16 files changed, 113 insertions(+), 126 deletions(-)

diff --git a/v2rayN/ServiceLib/Common/Utils.cs b/v2rayN/ServiceLib/Common/Utils.cs
index 0b0bd448..d78a52c1 100644
--- a/v2rayN/ServiceLib/Common/Utils.cs
+++ b/v2rayN/ServiceLib/Common/Utils.cs
@@ -110,7 +110,7 @@ namespace ServiceLib.Common
             catch (Exception ex)
             {
                 Logging.SaveLog(ex.Message, ex);
-                return new List<string>();
+                return [];
             }
         }
 
@@ -131,7 +131,7 @@ namespace ServiceLib.Common
             catch (Exception ex)
             {
                 Logging.SaveLog(ex.Message, ex);
-                return new List<string>();
+                return [];
             }
         }
 
@@ -640,29 +640,16 @@ namespace ServiceLib.Common
             return fileName;
         }
 
-        public static IPAddress? GetDefaultGateway()
-        {
-            return NetworkInterface
-                .GetAllNetworkInterfaces()
-                .Where(n => n.OperationalStatus == OperationalStatus.Up)
-                .Where(n => n.NetworkInterfaceType != NetworkInterfaceType.Loopback)
-                .SelectMany(n => n.GetIPProperties()?.GatewayAddresses)
-                .Select(g => g?.Address)
-                .Where(a => a != null)
-                // .Where(a => a.AddressFamily == AddressFamily.InterNetwork)
-                // .Where(a => Array.FindIndex(a.GetAddressBytes(), b => b != 0) >= 0)
-                .FirstOrDefault();
-        }
-
         public static bool IsGuidByParse(string strSrc)
         {
-            return Guid.TryParse(strSrc, out Guid g);
+            return Guid.TryParse(strSrc, out _);
         }
 
-        public static void ProcessStart(string fileName, string arguments = "")
+        public static void ProcessStart(string? fileName, string arguments = "")
         {
             try
             {
+                if (fileName.IsNullOrEmpty()) { return; }
                 Process.Start(new ProcessStartInfo(fileName, arguments) { UseShellExecute = true });
             }
             catch (Exception ex)
diff --git a/v2rayN/ServiceLib/Handler/ClashApiHandler.cs b/v2rayN/ServiceLib/Handler/ClashApiHandler.cs
index 1084cd4c..c27dda9e 100644
--- a/v2rayN/ServiceLib/Handler/ClashApiHandler.cs
+++ b/v2rayN/ServiceLib/Handler/ClashApiHandler.cs
@@ -10,12 +10,12 @@ namespace ServiceLib.Handler
         private Dictionary<String, ProxiesItem>? _proxies;
         public Dictionary<string, object> ProfileContent { get; set; }
 
-        public void GetClashProxies(Config config, Action<ClashProxies, ClashProviders> update)
+        public void GetClashProxies(Config config, Action<ClashProxies, ClashProviders> updateFunc)
         {
-            Task.Run(() => GetClashProxiesAsync(config, update));
+            Task.Run(() => GetClashProxiesAsync(config, updateFunc));
         }
 
-        private async Task GetClashProxiesAsync(Config config, Action<ClashProxies, ClashProviders> update)
+        private async Task GetClashProxiesAsync(Config config, Action<ClashProxies, ClashProviders> updateFunc)
         {
             for (var i = 0; i < 5; i++)
             {
@@ -30,15 +30,15 @@ namespace ServiceLib.Handler
                 if (clashProxies != null || clashProviders != null)
                 {
                     _proxies = clashProxies?.proxies;
-                    update(clashProxies, clashProviders);
+                    updateFunc?.Invoke(clashProxies, clashProviders);
                     return;
                 }
                 Task.Delay(5000).Wait();
             }
-            update(null, null);
+            updateFunc?.Invoke(null, null);
         }
 
-        public void ClashProxiesDelayTest(bool blAll, List<ClashProxyModel> lstProxy, Action<ClashProxyModel?, string> update)
+        public void ClashProxiesDelayTest(bool blAll, List<ClashProxyModel> lstProxy, Action<ClashProxyModel?, string> updateFunc)
         {
             Task.Run(() =>
             {
@@ -90,13 +90,13 @@ namespace ServiceLib.Handler
                     tasks.Add(Task.Run(async () =>
                     {
                         var result = await HttpClientHelper.Instance.TryGetAsync(url);
-                        update(it, result);
+                        updateFunc?.Invoke(it, result);
                     }));
                 }
                 Task.WaitAll(tasks.ToArray());
 
                 Task.Delay(1000).Wait();
-                update(null, "");
+                updateFunc?.Invoke(null, "");
             });
         }
 
@@ -164,12 +164,12 @@ namespace ServiceLib.Handler
             }
         }
 
-        public void GetClashConnections(Config config, Action<ClashConnections> update)
+        public void GetClashConnections(Config config, Action<ClashConnections> updateFunc)
         {
-            Task.Run(() => GetClashConnectionsAsync(config, update));
+            Task.Run(() => GetClashConnectionsAsync(config, updateFunc));
         }
 
-        private async Task GetClashConnectionsAsync(Config config, Action<ClashConnections> update)
+        private async Task GetClashConnectionsAsync(Config config, Action<ClashConnections> updateFunc)
         {
             try
             {
@@ -177,7 +177,7 @@ namespace ServiceLib.Handler
                 var result = await HttpClientHelper.Instance.TryGetAsync(url);
                 var clashConnections = JsonUtils.Deserialize<ClashConnections>(result);
 
-                update(clashConnections);
+                updateFunc?.Invoke(clashConnections);
             }
             catch (Exception ex)
             {
diff --git a/v2rayN/ServiceLib/Handler/CoreHandler.cs b/v2rayN/ServiceLib/Handler/CoreHandler.cs
index 985eb1d6..3c2667e2 100644
--- a/v2rayN/ServiceLib/Handler/CoreHandler.cs
+++ b/v2rayN/ServiceLib/Handler/CoreHandler.cs
@@ -13,12 +13,12 @@ namespace ServiceLib.Handler
         private Config _config;
         private Process? _process;
         private Process? _processPre;
-        private Action<bool, string> _updateFunc;
+        private Action<bool, string>? _updateFunc;
 
-        public void Init(Config config, Action<bool, string> update)
+        public void Init(Config config, Action<bool, string> updateFunc)
         {
             _config = config;
-            _updateFunc = update;
+            _updateFunc = updateFunc;
 
             Environment.SetEnvironmentVariable("v2ray.location.asset", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
             Environment.SetEnvironmentVariable("xray.location.asset", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
@@ -267,7 +267,7 @@ namespace ServiceLib.Handler
 
         private void ShowMsg(bool notify, string msg)
         {
-            _updateFunc(notify, msg);
+            _updateFunc?.Invoke(notify, msg);
         }
 
         #endregion Private
diff --git a/v2rayN/ServiceLib/Handler/StatisticsHandler.cs b/v2rayN/ServiceLib/Handler/StatisticsHandler.cs
index 29f2ae70..9ce5150a 100644
--- a/v2rayN/ServiceLib/Handler/StatisticsHandler.cs
+++ b/v2rayN/ServiceLib/Handler/StatisticsHandler.cs
@@ -8,16 +8,16 @@
         private Config _config;
         private ServerStatItem? _serverStatItem;
         private List<ServerStatItem> _lstServerStat;
-        private Action<ServerSpeedItem> _updateFunc;
+        private Action<ServerSpeedItem>? _updateFunc;
         private StatisticsV2rayService? _statisticsV2Ray;
         private StatisticsSingboxService? _statisticsSingbox;
 
         public List<ServerStatItem> ServerStat => _lstServerStat;
 
-        public void Init(Config config, Action<ServerSpeedItem> update)
+        public void Init(Config config, Action<ServerSpeedItem> updateFunc)
         {
             _config = config;
-            _updateFunc = update;
+            _updateFunc = updateFunc;
             if (!config.guiItem.enableStatistics)
             {
                 return;
@@ -95,7 +95,7 @@
             server.todayDown = _serverStatItem.todayDown;
             server.totalUp = _serverStatItem.totalUp;
             server.totalDown = _serverStatItem.totalDown;
-            _updateFunc(server);
+            _updateFunc?.Invoke(server);
         }
 
         private void GetServerStatItem(string indexId)
diff --git a/v2rayN/ServiceLib/Handler/TaskHandler.cs b/v2rayN/ServiceLib/Handler/TaskHandler.cs
index 7ab58092..a75470c2 100644
--- a/v2rayN/ServiceLib/Handler/TaskHandler.cs
+++ b/v2rayN/ServiceLib/Handler/TaskHandler.cs
@@ -9,13 +9,13 @@
         {
         }
 
-        public void RegUpdateTask(Config config, Action<bool, string> update)
+        public void RegUpdateTask(Config config, Action<bool, string> updateFunc)
         {
-            Task.Run(() => UpdateTaskRunSubscription(config, update));
-            Task.Run(() => UpdateTaskRunGeo(config, update));
+            Task.Run(() => UpdateTaskRunSubscription(config, updateFunc));
+            Task.Run(() => UpdateTaskRunGeo(config, updateFunc));
         }
 
-        private async Task UpdateTaskRunSubscription(Config config, Action<bool, string> update)
+        private async Task UpdateTaskRunSubscription(Config config, Action<bool, string> updateFunc)
         {
             await Task.Delay(60000);
             Logging.SaveLog("UpdateTaskRunSubscription");
@@ -33,7 +33,7 @@
                 {
                     updateHandle.UpdateSubscriptionProcess(config, item.id, true, (bool success, string msg) =>
                     {
-                        update(success, msg);
+                        updateFunc?.Invoke(success, msg);
                         if (success)
                             Logging.SaveLog("subscription" + msg);
                     });
@@ -46,7 +46,7 @@
             }
         }
 
-        private async Task UpdateTaskRunGeo(Config config, Action<bool, string> update)
+        private async Task UpdateTaskRunGeo(Config config, Action<bool, string> updateFunc)
         {
             var autoUpdateGeoTime = DateTime.Now;
 
@@ -65,7 +65,7 @@
                     {
                         await updateHandle.UpdateGeoFileAll(config, (bool success, string msg) =>
                         {
-                            update(false, msg);
+                            updateFunc?.Invoke(false, msg);
                         });
                         autoUpdateGeoTime = dtNow;
                     }
diff --git a/v2rayN/ServiceLib/ServiceLib.csproj b/v2rayN/ServiceLib/ServiceLib.csproj
index 8ff61685..ab44a0c9 100644
--- a/v2rayN/ServiceLib/ServiceLib.csproj
+++ b/v2rayN/ServiceLib/ServiceLib.csproj
@@ -8,14 +8,14 @@
   </PropertyGroup>
 
 	<ItemGroup>
-		<PackageReference Include="Downloader" Version="3.2.0" />
+		<PackageReference Include="Downloader" Version="3.2.1" />
 		<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
 		<PackageReference Include="ReactiveUI" Version="20.1.63" />
 		<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
 		<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
 		<PackageReference Include="Splat.NLog" Version="15.2.22" />
 		<PackageReference Include="WebDav.Client" Version="2.8.0" />
-		<PackageReference Include="YamlDotNet" Version="16.1.2" />
+		<PackageReference Include="YamlDotNet" Version="16.1.3" />
 		<PackageReference Include="QRCoder" Version="1.6.0" />
 		<PackageReference Include="CliWrap" Version="3.6.6" />
 	</ItemGroup>
diff --git a/v2rayN/ServiceLib/Services/DownloadService.cs b/v2rayN/ServiceLib/Services/DownloadService.cs
index bd6dc362..97d1080e 100644
--- a/v2rayN/ServiceLib/Services/DownloadService.cs
+++ b/v2rayN/ServiceLib/Services/DownloadService.cs
@@ -26,7 +26,7 @@ namespace ServiceLib.Services
             }
         }
 
-        public async Task<int> DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Action<bool, string> update)
+        public async Task<int> DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Action<bool, string> updateFunc)
         {
             try
             {
@@ -35,10 +35,10 @@ namespace ServiceLib.Services
                 var progress = new Progress<string>();
                 progress.ProgressChanged += (sender, value) =>
                 {
-                    if (update != null)
+                    if (updateFunc != null)
                     {
                         string msg = $"{value}";
-                        update(false, msg);
+                        updateFunc?.Invoke(false, msg);
                     }
                 };
 
@@ -49,10 +49,10 @@ namespace ServiceLib.Services
             }
             catch (Exception ex)
             {
-                update(false, ex.Message);
+                updateFunc?.Invoke(false, ex.Message);
                 if (ex.InnerException != null)
                 {
-                    update(false, ex.InnerException.Message);
+                    updateFunc?.Invoke(false, ex.InnerException.Message);
                 }
             }
             return 0;
diff --git a/v2rayN/ServiceLib/Services/SpeedtestService.cs b/v2rayN/ServiceLib/Services/SpeedtestService.cs
index a708416a..588e2eef 100644
--- a/v2rayN/ServiceLib/Services/SpeedtestService.cs
+++ b/v2rayN/ServiceLib/Services/SpeedtestService.cs
@@ -9,15 +9,15 @@ namespace ServiceLib.Services
         private Config? _config;
         private List<ServerTestItem> _selecteds;
         private ESpeedActionType _actionType;
-        private Action<SpeedTestResult> _updateFunc;
+        private Action<SpeedTestResult>? _updateFunc;
         private bool _exitLoop = false;
 
-        public SpeedtestService(Config config, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> update)
+        public SpeedtestService(Config config, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> updateFunc)
         {
             _config = config;
 
             _actionType = actionType;
-            _updateFunc = update;
+            _updateFunc = updateFunc;
 
             _selecteds = new List<ServerTestItem>();
             foreach (var it in selecteds)
@@ -383,7 +383,7 @@ namespace ServiceLib.Services
 
         private void UpdateFunc(string indexId, string delay, string speed = "")
         {
-            _updateFunc(new() { IndexId = indexId, Delay = delay, Speed = speed });
+            _updateFunc?.Invoke(new() { IndexId = indexId, Delay = delay, Speed = speed });
         }
     }
 }
\ No newline at end of file
diff --git a/v2rayN/ServiceLib/Services/Statistics/StatisticsSingboxService.cs b/v2rayN/ServiceLib/Services/Statistics/StatisticsSingboxService.cs
index fac3d1b7..3b7d0484 100644
--- a/v2rayN/ServiceLib/Services/Statistics/StatisticsSingboxService.cs
+++ b/v2rayN/ServiceLib/Services/Statistics/StatisticsSingboxService.cs
@@ -9,12 +9,12 @@ namespace ServiceLib.Services.Statistics
         private bool _exitFlag;
         private ClientWebSocket? webSocket;
         private string url = string.Empty;
-        private Action<ServerSpeedItem> _updateFunc;
+        private Action<ServerSpeedItem>? _updateFunc;
 
-        public StatisticsSingboxService(Config config, Action<ServerSpeedItem> update)
+        public StatisticsSingboxService(Config config, Action<ServerSpeedItem> updateFunc)
         {
             _config = config;
-            _updateFunc = update;
+            _updateFunc = updateFunc;
             _exitFlag = false;
 
             Task.Run(() => Run());
@@ -92,7 +92,7 @@ namespace ServiceLib.Services.Statistics
                             {
                                 ParseOutput(result, out ulong up, out ulong down);
 
-                                _updateFunc(new ServerSpeedItem()
+                                _updateFunc?.Invoke(new ServerSpeedItem()
                                 {
                                     proxyUp = (long)(up / 1000),
                                     proxyDown = (long)(down / 1000)
diff --git a/v2rayN/ServiceLib/Services/Statistics/StatisticsV2rayService.cs b/v2rayN/ServiceLib/Services/Statistics/StatisticsV2rayService.cs
index a35266ef..440a6772 100644
--- a/v2rayN/ServiceLib/Services/Statistics/StatisticsV2rayService.cs
+++ b/v2rayN/ServiceLib/Services/Statistics/StatisticsV2rayService.cs
@@ -10,12 +10,12 @@ namespace ServiceLib.Services.Statistics
         private GrpcChannel? _channel;
         private StatsService.StatsServiceClient? _client;
         private bool _exitFlag;
-        private Action<ServerSpeedItem> _updateFunc;
+        private Action<ServerSpeedItem>? _updateFunc;
 
-        public StatisticsV2rayService(Models.Config config, Action<ServerSpeedItem> update)
+        public StatisticsV2rayService(Models.Config config, Action<ServerSpeedItem> updateFunc)
         {
             _config = config;
-            _updateFunc = update;
+            _updateFunc = updateFunc;
             _exitFlag = false;
 
             GrpcInit();
@@ -70,7 +70,7 @@ namespace ServiceLib.Services.Statistics
                         if (res != null)
                         {
                             ParseOutput(res.Stat, out ServerSpeedItem server);
-                            _updateFunc(server);
+                            _updateFunc?.Invoke(server);
                         }
                     }
                     if (_channel != null)
diff --git a/v2rayN/ServiceLib/Services/UpdateService.cs b/v2rayN/ServiceLib/Services/UpdateService.cs
index f9b7babc..02d54f06 100644
--- a/v2rayN/ServiceLib/Services/UpdateService.cs
+++ b/v2rayN/ServiceLib/Services/UpdateService.cs
@@ -7,7 +7,7 @@ namespace ServiceLib.Services
 {
     public class UpdateService
     {
-        private Action<bool, string> _updateFunc;
+        private Action<bool, string>? _updateFunc;
         private Config _config;
         private int _timeout = 30;
 
@@ -25,10 +25,10 @@ namespace ServiceLib.Services
             }
         }
 
-        public async Task CheckUpdateGuiN(Config config, Action<bool, string> update, bool preRelease)
+        public async Task CheckUpdateGuiN(Config config, Action<bool, string> updateFunc, bool preRelease)
         {
             _config = config;
-            _updateFunc = update;
+            _updateFunc = updateFunc;
             var url = string.Empty;
             var fileName = string.Empty;
 
@@ -37,25 +37,25 @@ namespace ServiceLib.Services
             {
                 if (args.Success)
                 {
-                    _updateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully);
-                    _updateFunc(true, Utils.UrlEncode(fileName));
+                    _updateFunc?.Invoke(false, ResUI.MsgDownloadV2rayCoreSuccessfully);
+                    _updateFunc?.Invoke(true, Utils.UrlEncode(fileName));
                 }
                 else
                 {
-                    _updateFunc(false, args.Msg);
+                    _updateFunc?.Invoke(false, args.Msg);
                 }
             };
             downloadHandle.Error += (sender2, args) =>
             {
-                _updateFunc(false, args.GetException().Message);
+                _updateFunc?.Invoke(false, args.GetException().Message);
             };
 
-            _updateFunc(false, string.Format(ResUI.MsgStartUpdating, ECoreType.v2rayN));
+            _updateFunc?.Invoke(false, string.Format(ResUI.MsgStartUpdating, ECoreType.v2rayN));
             var args = await CheckUpdateAsync(downloadHandle, ECoreType.v2rayN, preRelease);
             if (args.Success)
             {
-                _updateFunc(false, string.Format(ResUI.MsgParsingSuccessfully, ECoreType.v2rayN));
-                _updateFunc(false, args.Msg);
+                _updateFunc?.Invoke(false, string.Format(ResUI.MsgParsingSuccessfully, ECoreType.v2rayN));
+                _updateFunc?.Invoke(false, args.Msg);
 
                 url = args.Url;
                 fileName = Utils.GetTempPath(Utils.GetGUID());
@@ -63,14 +63,14 @@ namespace ServiceLib.Services
             }
             else
             {
-                _updateFunc(false, args.Msg);
+                _updateFunc?.Invoke(false, args.Msg);
             }
         }
 
-        public async Task CheckUpdateCore(ECoreType type, Config config, Action<bool, string> update, bool preRelease)
+        public async Task CheckUpdateCore(ECoreType type, Config config, Action<bool, string> updateFunc, bool preRelease)
         {
             _config = config;
-            _updateFunc = update;
+            _updateFunc = updateFunc;
             var url = string.Empty;
             var fileName = string.Empty;
 
@@ -79,34 +79,34 @@ namespace ServiceLib.Services
             {
                 if (args.Success)
                 {
-                    _updateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully);
-                    _updateFunc(false, ResUI.MsgUnpacking);
+                    _updateFunc?.Invoke(false, ResUI.MsgDownloadV2rayCoreSuccessfully);
+                    _updateFunc?.Invoke(false, ResUI.MsgUnpacking);
 
                     try
                     {
-                        _updateFunc(true, fileName);
+                        _updateFunc?.Invoke(true, fileName);
                     }
                     catch (Exception ex)
                     {
-                        _updateFunc(false, ex.Message);
+                        _updateFunc?.Invoke(false, ex.Message);
                     }
                 }
                 else
                 {
-                    _updateFunc(false, args.Msg);
+                    _updateFunc?.Invoke(false, args.Msg);
                 }
             };
             downloadHandle.Error += (sender2, args) =>
             {
-                _updateFunc(false, args.GetException().Message);
+                _updateFunc?.Invoke(false, args.GetException().Message);
             };
 
-            _updateFunc(false, string.Format(ResUI.MsgStartUpdating, type));
+            _updateFunc?.Invoke(false, string.Format(ResUI.MsgStartUpdating, type));
             var args = await CheckUpdateAsync(downloadHandle, type, preRelease);
             if (args.Success)
             {
-                _updateFunc(false, string.Format(ResUI.MsgParsingSuccessfully, type));
-                _updateFunc(false, args.Msg);
+                _updateFunc?.Invoke(false, string.Format(ResUI.MsgParsingSuccessfully, type));
+                _updateFunc?.Invoke(false, args.Msg);
 
                 url = args.Url;
                 var ext = Path.GetExtension(url);
@@ -117,22 +117,22 @@ namespace ServiceLib.Services
             {
                 if (!args.Msg.IsNullOrEmpty())
                 {
-                    _updateFunc(false, args.Msg);
+                    _updateFunc?.Invoke(false, args.Msg);
                 }
             }
         }
 
-        public void UpdateSubscriptionProcess(Config config, string subId, bool blProxy, Action<bool, string> update)
+        public void UpdateSubscriptionProcess(Config config, string subId, bool blProxy, Action<bool, string> updateFunc)
         {
             _config = config;
-            _updateFunc = update;
+            _updateFunc = updateFunc;
 
-            _updateFunc(false, ResUI.MsgUpdateSubscriptionStart);
+            _updateFunc?.Invoke(false, ResUI.MsgUpdateSubscriptionStart);
             var subItem = AppHandler.Instance.SubItems().OrderBy(t => t.sort).ToList();
 
             if (subItem == null || subItem.Count <= 0)
             {
-                _updateFunc(false, ResUI.MsgNoValidSubscription);
+                _updateFunc?.Invoke(false, ResUI.MsgNoValidSubscription);
                 return;
             }
 
@@ -146,7 +146,7 @@ namespace ServiceLib.Services
                     string hashCode = $"{item.remarks}->";
                     if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url) || Utils.IsNotEmpty(subId) && item.id != subId)
                     {
-                        //_updateFunc(false, $"{hashCode}{ResUI.MsgNoValidSubscription}");
+                        //_updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgNoValidSubscription}");
                         continue;
                     }
                     if (!url.StartsWith(Global.HttpsProtocol) && !url.StartsWith(Global.HttpProtocol))
@@ -155,17 +155,17 @@ namespace ServiceLib.Services
                     }
                     if (item.enabled == false)
                     {
-                        _updateFunc(false, $"{hashCode}{ResUI.MsgSkipSubscriptionUpdate}");
+                        _updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgSkipSubscriptionUpdate}");
                         continue;
                     }
 
                     var downloadHandle = new DownloadService();
                     downloadHandle.Error += (sender2, args) =>
                     {
-                        _updateFunc(false, $"{hashCode}{args.GetException().Message}");
+                        _updateFunc?.Invoke(false, $"{hashCode}{args.GetException().Message}");
                     };
 
-                    _updateFunc(false, $"{hashCode}{ResUI.MsgStartGettingSubscriptions}");
+                    _updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgStartGettingSubscriptions}");
 
                     //one url
                     url = Utils.GetPunycode(url);
@@ -227,14 +227,14 @@ namespace ServiceLib.Services
 
                     if (Utils.IsNullOrEmpty(result))
                     {
-                        _updateFunc(false, $"{hashCode}{ResUI.MsgSubscriptionDecodingFailed}");
+                        _updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgSubscriptionDecodingFailed}");
                     }
                     else
                     {
-                        _updateFunc(false, $"{hashCode}{ResUI.MsgGetSubscriptionSuccessfully}");
+                        _updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgGetSubscriptionSuccessfully}");
                         if (result?.Length < 99)
                         {
-                            _updateFunc(false, $"{hashCode}{result}");
+                            _updateFunc?.Invoke(false, $"{hashCode}{result}");
                         }
 
                         int ret = ConfigHandler.AddBatchServers(config, result, id, true);
@@ -243,29 +243,29 @@ namespace ServiceLib.Services
                             Logging.SaveLog("FailedImportSubscription");
                             Logging.SaveLog(result);
                         }
-                        _updateFunc(false,
+                        _updateFunc?.Invoke(false,
                             ret > 0
                                 ? $"{hashCode}{ResUI.MsgUpdateSubscriptionEnd}"
                                 : $"{hashCode}{ResUI.MsgFailedImportSubscription}");
                     }
-                    _updateFunc(false, "-------------------------------------------------------");
+                    _updateFunc?.Invoke(false, "-------------------------------------------------------");
                 }
 
-                _updateFunc(true, $"{ResUI.MsgUpdateSubscriptionEnd}");
+                _updateFunc?.Invoke(true, $"{ResUI.MsgUpdateSubscriptionEnd}");
             });
         }
 
-        public async Task UpdateGeoFileAll(Config config, Action<bool, string> update)
+        public async Task UpdateGeoFileAll(Config config, Action<bool, string> updateFunc)
         {
-            await UpdateGeoFile("geosite", _config, update);
-            await UpdateGeoFile("geoip", _config, update);
-            _updateFunc(true, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, "geo"));
+            await UpdateGeoFile("geosite", _config, updateFunc);
+            await UpdateGeoFile("geoip", _config, updateFunc);
+            _updateFunc?.Invoke(true, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, "geo"));
         }
 
-        public async Task RunAvailabilityCheck(Action<bool, string> update)
+        public async Task RunAvailabilityCheck(Action<bool, string> updateFunc)
         {
             var time = await new DownloadService().RunAvailabilityCheck(null);
-            update(false, string.Format(ResUI.TestMeOutput, time));
+            updateFunc?.Invoke(false, string.Format(ResUI.TestMeOutput, time));
         }
 
         #region private
@@ -290,7 +290,7 @@ namespace ServiceLib.Services
             catch (Exception ex)
             {
                 Logging.SaveLog(ex.Message, ex);
-                _updateFunc(false, ex.Message);
+                _updateFunc?.Invoke(false, ex.Message);
                 return new ResultEventArgs(false, ex.Message);
             }
         }
@@ -355,7 +355,7 @@ namespace ServiceLib.Services
             catch (Exception ex)
             {
                 Logging.SaveLog(ex.Message, ex);
-                _updateFunc(false, ex.Message);
+                _updateFunc?.Invoke(false, ex.Message);
                 return new SemanticVersion("");
             }
         }
@@ -419,7 +419,7 @@ namespace ServiceLib.Services
             catch (Exception ex)
             {
                 Logging.SaveLog(ex.Message, ex);
-                _updateFunc(false, ex.Message);
+                _updateFunc?.Invoke(false, ex.Message);
                 return new ResultEventArgs(false, ex.Message);
             }
         }
@@ -457,10 +457,10 @@ namespace ServiceLib.Services
             return null;
         }
 
-        private async Task UpdateGeoFile(string geoName, Config config, Action<bool, string> update)
+        private async Task UpdateGeoFile(string geoName, Config config, Action<bool, string> updateFunc)
         {
             _config = config;
-            _updateFunc = update;
+            _updateFunc = updateFunc;
             var url = string.Format(Global.GeoUrl, geoName);
             var fileName = Utils.GetTempPath(Utils.GetGUID());
 
@@ -469,7 +469,7 @@ namespace ServiceLib.Services
             {
                 if (args.Success)
                 {
-                    _updateFunc(false, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, geoName));
+                    _updateFunc?.Invoke(false, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, geoName));
 
                     try
                     {
@@ -479,22 +479,22 @@ namespace ServiceLib.Services
                             File.Copy(fileName, targetPath, true);
 
                             File.Delete(fileName);
-                            //_updateFunc(true, "");
+                            //_updateFunc?.Invoke(true, "");
                         }
                     }
                     catch (Exception ex)
                     {
-                        _updateFunc(false, ex.Message);
+                        _updateFunc?.Invoke(false, ex.Message);
                     }
                 }
                 else
                 {
-                    _updateFunc(false, args.Msg);
+                    _updateFunc?.Invoke(false, args.Msg);
                 }
             };
             downloadHandle.Error += (sender2, args) =>
             {
-                _updateFunc(false, args.GetException().Message);
+                _updateFunc?.Invoke(false, args.GetException().Message);
             };
 
             await downloadHandle.DownloadFileAsync(url, fileName, true, _timeout);
diff --git a/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs b/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs
index e0e6f7da..4fc51b1e 100644
--- a/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs
+++ b/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs
@@ -32,7 +32,7 @@ namespace ServiceLib.ViewModels
                 await CheckUpdate()
                 .ContinueWith(t =>
                 {
-                    UpdateFinished();
+                    _ = UpdateFinished();
                 });
             });
             EnableCheckPreReleaseUpdate = _config.guiItem.checkPreReleaseUpdate;
diff --git a/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs b/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs
index cccbc00d..13de1799 100644
--- a/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs
+++ b/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs
@@ -38,9 +38,9 @@ namespace ServiceLib.ViewModels
             normalDNS2 = item2?.normalDNS ?? string.Empty;
             tunDNS2 = item2?.tunDNS ?? string.Empty;
 
-            SaveCmd = ReactiveCommand.Create(() =>
+            SaveCmd = ReactiveCommand.CreateFromTask(async () =>
             {
-                SaveSettingAsync();
+                await SaveSettingAsync();
             });
 
             ImportDefConfig4V2rayCmd = ReactiveCommand.Create(() =>
@@ -65,7 +65,7 @@ namespace ServiceLib.ViewModels
                 }
                 else
                 {
-                    if (normalDNS.Contains("{") || normalDNS.Contains("}"))
+                    if (normalDNS.Contains('{') || normalDNS.Contains('}'))
                     {
                         NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText);
                         return;
diff --git a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs
index 188d1810..b4ccc9d2 100644
--- a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs
+++ b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs
@@ -453,7 +453,7 @@ namespace v2rayN.Desktop.Views
             {
                 var item = new MenuItem()
                 {
-                    Tag = it.Url.Replace(@"/releases", ""),
+                    Tag = it.Url?.Replace(@"/releases", ""),
                     Header = string.Format(ResUI.menuWebsiteItem, it.CoreType.ToString().Replace("_", " ")).UpperFirstChar()
                 };
                 item.Click += MenuItem_Click;
@@ -465,7 +465,7 @@ namespace v2rayN.Desktop.Views
         {
             if (sender is MenuItem item)
             {
-                Utils.ProcessStart(item.Tag.ToString());
+                Utils.ProcessStart(item.Tag?.ToString());
             }
         }
 
diff --git a/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj b/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj
index e0a8cb1e..e6b29cd2 100644
--- a/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj
+++ b/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj
@@ -25,7 +25,7 @@
         <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.1.3" />
         <PackageReference Include="Avalonia.ReactiveUI" Version="11.1.3" />
         <PackageReference Include="DialogHost.Avalonia" Version="0.8.1" />
-        <PackageReference Include="MessageBox.Avalonia" Version="3.1.6" />		
+        <PackageReference Include="MessageBox.Avalonia" Version="3.1.6.13" />		
         <PackageReference Include="Semi.Avalonia" Version="11.1.0.4" />
         <PackageReference Include="Semi.Avalonia.DataGrid" Version="11.1.0.4" />
         <PackageReference Include="ReactiveUI" Version="20.1.63" />
diff --git a/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs b/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs
index aa20ee0e..dcee4916 100644
--- a/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs
+++ b/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs
@@ -185,7 +185,7 @@ namespace v2rayN.ViewModels
             _paletteHelper.SetTheme(theme);
         }
 
-        public void RegisterSystemColorSet(Config config, Window window, Action<bool> update)
+        public void RegisterSystemColorSet(Config config, Window window, Action<bool> updateFunc)
         {
             var helper = new WindowInteropHelper(window);
             var hwndSource = HwndSource.FromHwnd(helper.EnsureHandle());
@@ -198,7 +198,7 @@ namespace v2rayN.ViewModels
                     {
                         if (wParam == IntPtr.Zero && Marshal.PtrToStringUni(lParam) == "ImmersiveColorSet")
                         {
-                            update(!WindowsUtils.IsLightTheme());
+                            updateFunc?.Invoke(!WindowsUtils.IsLightTheme());
                         }
                     }
                 }