WPF MVVM应用系统日期与互联网日期校验及网络判断异常问题
问题:断开互联网后
CheckNetConnectivity()仍返回true,无法触发无网络提示 在WPF MVVM应用中,使用InternetGetConnectedState检测网络连接时,即使断开互联网(仅保留局域网连接),该方法依然返回true,导致无法进入无网络的提示分支。同时当前代码未处理网络请求异常,存在潜在崩溃风险。
核心原因
InternetGetConnectedState仅检测系统是否存在网络连接(如局域网),无法验证是否能访问外部互联网服务器。因此需要通过实际请求目标服务器来确认网络可用性。
解决方案
方案1:替换网络检测逻辑,直接验证目标服务器可达
将原CheckNetConnectivity改为尝试连接Google服务器(与获取时间的目标一致),确保网络真正可用:
using System; using System.Globalization; using System.Net.Http; public static class DateVerifications { public static bool CheckNetConnectivity() { try { using var client = new HttpClient(); client.Timeout = TimeSpan.FromSeconds(5); // 发送HEAD请求,仅获取响应头,比GET更轻量高效 var response = client.SendAsync(new HttpRequestMessage(HttpMethod.Head, "http://www.google.com")).Result; return response.IsSuccessStatusCode; } catch { // 任何异常(超时、连接失败等)均视为网络不可用 return false; } } public static DateTime GetGoogleTime() { using var client = new HttpClient(); client.Timeout = TimeSpan.FromSeconds(5); var response = client.GetAsync("http://www.google.com").Result; if (!response.Headers.Date.HasValue) throw new InvalidOperationException("无法获取服务器时间"); return response.Headers.Date.Value.UtcDateTime; } }
方案2:保留原检测,在ViewModel中捕获请求异常
如果不想修改网络检测方法,可在ViewModel中捕获GetGoogleTime的异常,当请求失败时切换到无网络提示:
private string _dtm; public string dtm { get { if (DateVerifications.CheckNetConnectivity()) { try { var serverDate = DateVerifications.GetGoogleTime().ToString("dd-MM-yyyy"); var localDate = DateTime.Today.ToString("dd-MM-yyyy"); return _dtm = localDate == serverDate ? "System date verified!" : "System date is not correct!"; } catch (Exception) { // 请求失败,说明实际无互联网 return _dtm = "System date cannot be verified! No internet!!!"; } } else { return _dtm = "System date cannot be verified! No internet!!!"; } } }
额外优化建议
- 替换
HttpWebRequest为HttpClient:HttpClient是.NET官方推荐的现代网络请求类,更简洁、性能更优。 - 避免在属性
get中执行耗时操作:网络请求是异步操作,同步执行会导致UI卡顿。建议在ViewModel构造函数中异步执行验证,通过INotifyPropertyChanged更新属性:
using System; using System.ComponentModel; using System.Net.Http; using System.Runtime.CompilerServices; using System.Threading.Tasks; public class YourViewModel : INotifyPropertyChanged { private string _dtm; public string dtm { get => _dtm; set { _dtm = value; OnPropertyChanged(); } } public YourViewModel() { // 异步执行日期验证,不阻塞UI线程 _ = VerifyDateAsync(); } private async Task VerifyDateAsync() { try { using var client = new HttpClient(); client.Timeout = TimeSpan.FromSeconds(5); // 先验证网络连通性 var headResponse = await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, "http://www.google.com")); if (!headResponse.IsSuccessStatusCode) { dtm = "System date cannot be verified! No internet!!!"; return; } // 获取服务器时间并对比 var getResponse = await client.GetAsync("http://www.google.com"); if (!getResponse.Headers.Date.HasValue) { dtm = "System date cannot be verified! Server error!!!"; return; } var serverDate = getResponse.Headers.Date.Value.UtcDateTime.ToString("dd-MM-yyyy"); var localDate = DateTime.Today.ToString("dd-MM-yyyy"); dtm = localDate == serverDate ? "System date verified!" : "System date is not correct!"; } catch { dtm = "System date cannot be verified! No internet!!!"; } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
内容的提问来源于stack exchange,提问作者Tamal Banerjee
相关产品推荐
相关产品推荐

