Сбой WiFiAdapter.ScanAsync () после потери установленного соединения WiFi - PullRequest
0 голосов
/ 14 мая 2018

Я работаю с Windows.Devices.WiFi API для приложения UWP HoloLens. Я сканирую доступные сети как можно чаще (вызывая Scan () для каждого кадра), используя логическое значение, для которого задано значение false прямо перед вызовом «await ScanAsync ()», и установлено значение 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» (я сделал снимок экрана, показывающий содержание исключения).

Thrown exception of ScanAsync()

Без try / catch это привело к закрытию моего асинхронного сканирования задач () без окончательной установки моего логического значения IsReady обратно в true, что привело к тому, что мое приложение больше не сканировало доступные сети. Проблема в том, что мое текущее решение - не что иное, как простой обходной путь, который на самом деле работает, но на самом деле не решает проблему, с которой я сталкиваюсь при использовании метода ScanAsync.

Я просто не могу понять, почему он так себя ведет. WiFiAdapter доступен, так что это, вероятно, не проблема. Есть ли способ проверить, не утрачено ли мое установленное соединение с желаемой сетью (например, когда я выключаю свою точку доступа)? Или есть способ сказать "ожидайте ScanAsync", чтобы отменить раньше, если это занимает слишком много времени? Я рад за каждую идею о вас, ребята!

Поздравления * 1019 Синяя книга *

-EDIT-

Мой полный класс выглядит следующим образом, и я создаю его один раз в другом скрипте, где затем вызываю необходимые функции.

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;
        }
    }
}
...