c# - WiFiAdapter.ScanAsync() 在失去已建立的 WiFi 连接后失败
问题描述
我正在为 UWP HoloLens 应用程序使用 Windows.Devices.WiFi API。我正在尽可能频繁地扫描可用网络(每帧调用 Scan()),方法是使用在调用“await ScanAsync()”之前设置为 false 的布尔值,并在异步完成后设置为 true,这导致每次刚完成时调用 ScanAsync() ,效果很好。像这样的东西:
public async Task Scan()
{
if (IsReady)
{
IsReady = false;
try
{
await MyWiFiAdapter.ScanAsync();
}
catch(Exception e)
{
string fail = e.ToString();
Success = false;
}
IsReady = true;
}
}
如果我想要的 SSID 可用,我使用“await WiFiAdapter.ConnectAsync()”连接到它,它工作得很好(我通过将 HoloLens 连接到我的智能手机的热点来检查它)。
现在到错误:
正在使用 HoloLens 连接到我的热点。如果我随后禁用我的热点,HoloLens 将失去连接,但会继续扫描并列出可用网络。如果我然后重新打开热点,“await WiFiAdapter.ScanAsync()”方法将需要大约 20 秒,然后失败并抛出类似于“操作中止,...TaskAwaiter.ThrowForNonSuccess”的异常(我制作了一个屏幕截图显示异常的内容)。
如果没有 try/catch,这会导致我的 async Task Scan() 退出而没有最终将我的布尔 IsReady 设置回 true,然后导致我的应用程序不再扫描可用网络。问题是,我当前的解决方案只不过是一个实际可行的简单解决方法,但实际上并没有解决我在使用 ScanAsync 方法时遇到的问题。
我只是不明白为什么它会这样。WiFiAdapter 可用,所以这可能不是问题。有没有办法检查我与所需网络的已建立连接是否丢失(就像我打开热点时一样)?或者有没有办法告诉“await ScanAsync”方法在需要太长时间时提前取消?我很高兴你们的每一个想法!
问候BB
-编辑-
我的完整类看起来像这样,我在另一个脚本中将它实例化一次,然后调用必要的函数。
using Assets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.WiFi;
using Windows.Networking.Connectivity;
namespace Assets
{
public class UniversalWiFi : IWiFiAdapter
{
private bool Success { get; set; }
private WiFiConnectionStatus MyConnectionStatus;
private bool IsReady { get; set; }
private bool InitialConnection { get; set; }
private uint Signal { get; set; }
private string Report { get; set; }
private string DesiredSsid { get; set; }
private string ConnectedSsid { get; set; }
private WiFiAdapter MyWiFiAdapter { get; set; }
private bool ReadyToConnect { get; set; }
public UniversalWiFi()
{
InitialConnection = true;
Success = false;
IsReady = true;
ReadyToConnect = true;
Signal = 0u;
DesiredSsid = "Desired SSID not yet defined";
ConnectedSsid = string.Empty;
Report = string.Empty;
}
public bool GetSuccess()
{
return Success;
}
public string GetNameOfConnectedSsid()
{
try
{
var connected = NetworkInformation.GetInternetConnectionProfile().WlanConnectionProfileDetails.GetConnectedSsid();
if (connected != null)
{
ConnectedSsid = connected;
}
else
{
ConnectedSsid = string.Empty;
}
}
catch
{
ConnectedSsid = string.Empty;
}
return ConnectedSsid;
}
public uint GetSignal(string ssid)
{
DesiredSsid = ssid;
return Signal;
}
private async Task InitiateGetAdapterAsync()
{
var result = await WiFiAdapter.FindAllAdaptersAsync();
if (result.Count >= 1)
{
MyWiFiAdapter = result[0];
}
InitialConnection = false;
}
public async Task Scan()
{
if (IsReady)
{
IsReady = false;
uint signal = 0u;
if (MyWiFiAdapter == null)
{
try
{
await InitiateGetAdapterAsync();
}
catch
{
MyWiFiAdapter = null;
}
}
else
{
try
{
await MyWiFiAdapter.ScanAsync();
GenerateNetworkReport(MyWiFiAdapter.NetworkReport);
if (!string.IsNullOrEmpty(DesiredSsid) && DesiredSSIDExists(MyWiFiAdapter.NetworkReport))
{
signal = GetNetworkSignal(MyWiFiAdapter.NetworkReport, DesiredSsid);
var desiredNW = MyWiFiAdapter.NetworkReport.AvailableNetworks.Where(y => y.Ssid == DesiredSsid).FirstOrDefault();
if ((ConnectedSsid != DesiredSsid) && (desiredNW != null))
{
if ((await MyWiFiAdapter.ConnectAsync(desiredNW, WiFiReconnectionKind.Manual)).ConnectionStatus == WiFiConnectionStatus.Success) //ReconnectionKind entspricht dem Häkchen "automatisch verbinden" in den Windows Einstellungen
{ //"Manual" da sich die HoloLens sonst teilweise über die App stellt und selbstständig verbindet
Success = true;
}
else
{
Success = false;
}
}
}
else
{
Success = false;
}
}
catch(Exception e)
{
string fail = e.ToString();
Success = false;
}
}
IsReady = true;
Signal = signal;
}
private bool DesiredSSIDExists(WiFiNetworkReport report)
{
var networks = new List<string>();
foreach (var network in report.AvailableNetworks)
{
networks.Add(string.Format("SSID: {0} -- SignalBars: {1} -- Db: {2} -- Mac: {3}",
network.Ssid, network.SignalBars, network.NetworkRssiInDecibelMilliwatts, network.Bssid));
}
var match = networks.FirstOrDefault(stringToCheck => stringToCheck.Contains(DesiredSsid));
if (match != null)
{
return true;
}
else
{
return false;
}
}
private uint GetNetworkSignal(WiFiNetworkReport report, string ssid)
{
var network = report.AvailableNetworks.Where(x => x.Ssid.ToLower() == ssid.ToLower()).FirstOrDefault();
if (network != null)
{
return network.SignalBars;
}
else
{
return 0u;
}
}
private void GenerateNetworkReport(WiFiNetworkReport report)
{
var networks = new List<string>();
foreach (var network in report.AvailableNetworks)
{
networks.Add(string.Format("SSID: {0} -- SignalBars: {1} -- Db: {2} -- Mac: {3}",
network.Ssid, network.SignalBars, network.NetworkRssiInDecibelMilliwatts, network.Bssid));
}
Report = string.Join(Environment.NewLine, networks.ToArray());
}
public string GetNetworkReport()
{
return Report;
}
}
}
解决方案
推荐阅读
- airflow - 在创建表之前,Airflow 在“airflow resetdb”时填充 DagBag 时引发错误
- python - 检查参数是否存在并相应地设置一个值
- string - 在 ABAP 调试器中查看长字符串的结尾
- android - 在 gradle android build 中使用 progaurd 生成 jar 文件
- c++ - 如何正确绑定成员函数与 boost::bind
- r - R:sapply 中的父赋值运算符
- node.js - 用于查询索引数据并按日期过滤的 Mongosastic 查询
- c - 使用函数时的异常堆栈条目
- hadoop - 在镶木地板文件上创建外部表时,BIGSQL 中的列顺序是否重要
- php - 带有自定义值的 Paypal 结帐表单