后台任务中的异步调用不起作用

本文关键字:调用 不起作用 异步 后台任务 | 更新日期: 2023-09-27 18:17:53

在我的应用程序中,我需要在后台扫描Wi-Fi接入点。我能够启动任务并初始化Wi-Fi适配器,但下一个异步调用"await scanner.ScanForNetworks()"来执行扫描似乎永远不会完成任务。这可能是许多嵌套异步调用的结果吗?如果是这样,有什么可能的解决方案?

ScanningTask.cs

namespace BackgroundTaskLibrary
{
    public sealed class ScanningTask : IBackgroundTask
    {
        private BackgroundTaskDeferral deferral;
        private WiFiScanner scanner = new WiFiScanner();
        private Windows.Storage.ApplicationDataContainer localSettings;
        private DispatcherTimer timer;
        public async void Run(IBackgroundTaskInstance taskInstance)
        {
            deferral = taskInstance.GetDeferral();
            taskInstance.Canceled += TaskInstance_Canceled;
            await scanner.InitializeFirstAdapter();
            ShowToastNotification("Hi", "Hello from background"); //notification is shown
            await scanner.ScanForNetworks();
            ShowToastNotification("Hi", "Hello from background1"); //this one never gets shown
            deferral.Complete();
        }
        private void TaskInstance_Canceled(IBackgroundTaskInstance sender, 
            BackgroundTaskCancellationReason reason)
        {
            deferral.Complete();
        }
        private void ShowToastNotification(string title, string stringContent)
        {
            ToastNotifier ToastNotifier = ToastNotificationManager.CreateToastNotifier();
            Windows.Data.Xml.Dom.XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
            Windows.Data.Xml.Dom.XmlNodeList toastNodeList = toastXml.GetElementsByTagName("text");
            toastNodeList.Item(0).AppendChild(toastXml.CreateTextNode(title));
            toastNodeList.Item(1).AppendChild(toastXml.CreateTextNode(stringContent));
            Windows.Data.Xml.Dom.IXmlNode toastNode = toastXml.SelectSingleNode("/toast");
            Windows.Data.Xml.Dom.XmlElement audio = toastXml.CreateElement("audio");
            audio.SetAttribute("src", "ms-winsoundevent:Notification.SMS");
            ToastNotification toast = new ToastNotification(toastXml);
            toast.ExpirationTime = DateTime.Now.AddSeconds(10);
            ToastNotifier.Show(toast);
        }
    }
}

WiFiAdapter.cs

namespace BackgroundTaskLibrary
{
    class WiFiScanner
    {
        //WiFi adapter instance
        public WiFiAdapter WiFiAdapter { get; private set; }
        public Geolocator _geolocator = new Geolocator();
        public Geoposition Location { get; set; }
        /// <summary>
        /// Find the fisrts available WiFi adapter and initialise it
        /// </summary>
        /// <returns></returns>
        public async Task InitializeFirstAdapter()
        {
            var access = await WiFiAdapter.RequestAccessAsync();
            if (access != WiFiAccessStatus.Allowed)
            {
                throw new Exception("WiFiAccessStatus not allowed");
            }
            else
            {
                var wifiAdapterResults =
                await DeviceInformation.FindAllAsync(WiFiAdapter.GetDeviceSelector());
                if (wifiAdapterResults.Count >= 1)
                {
                    this.WiFiAdapter =
                    await WiFiAdapter.FromIdAsync(wifiAdapterResults[0].Id);
                }
                else
                {
                    var dialog = new MessageDialog("WiFi Adapter not found.");
                    await dialog.ShowAsync();
                    throw new Exception("WiFi Adapter not found.");
                }
            }
        }
        public async Task ScanForNetworks()
        {
            if (WiFiAdapter != null)
            {
                await WiFiAdapter.ScanAsync();
            }
            else
            {
                throw new Exception("No Wi-Fi adapter");
            }
            Location = await _geolocator.GetGeopositionAsync();
            List<AccessPoint> accessPoints = new List<AccessPoint>();
            foreach(var network in WiFiAdapter.NetworkReport.AvailableNetworks)
            {
                AccessPoint ap = new AccessPoint()
                {
                    SSID = network.Ssid,
                    Mac = network.Bssid,
                    SignalStrength = network.NetworkRssiInDecibelMilliwatts,
                    Open = (int)network.SecuritySettings.NetworkAuthenticationType
                };
                accessPoints.Add(ap);
            }
            await SaveData(accessPoints);
        }
        public async Task SaveData(List<AccessPoint> accessPoints)
        {
            string info = DateTime.Now + "|" + Location.Coordinate.Point.Position.Latitude
                    + "|" + Location.Coordinate.Point.Position.Longitude + "|";
            for (int i = 0; i < accessPoints.Count; i++)
            {
                info += accessPoints[i].ToString();
            }
            info += Environment.NewLine;
            // Get the logical root folder for all external storage devices.
            StorageFolder externalDevices = Windows.Storage.KnownFolders.RemovableDevices;
            // Get the first child folder, which represents the SD card.
            StorageFolder sdCard = (await externalDevices.GetFoldersAsync()).FirstOrDefault();

            StorageFile infoFile;
            if (sdCard != null)
            {
                //check if info file exists
                try
                {
                    infoFile = await sdCard.GetFileAsync("wifiScanInfo.txt");
                }
                catch
                {
                    infoFile = await sdCard.CreateFileAsync("wifiScanInfo.txt");
                }
                await FileIO.AppendTextAsync(infoFile, info);
            }
        }
    }
}

如果您需要整个项目:https://www.dropbox.com/sh/1v9mbr3xhgr3283/AACDbB7skZUI7Z5fiu0HT8r4a?dl=0

编辑:

通过随后简化ScanningTask,我能够确定,问题是在调用"await WiFiAdapter.ScanAsync();"

我终于设法从"await WiFiAdapter.ScanAsync();"中捕获了一个异常,下面是堆栈跟踪:

Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at BackgroundTaskLibrary.WiFiScanner.<ScanForNetworks>d__10.MoveNext()

然而,扫描已经完成,结果如预期一样保存在文本文件中。我可能缺少哪些权限?我已经声明了互联网,位置和可移动存储权限。

后台任务中的异步调用不起作用

它认为异常来自使用GeoLocator而没有requestAccessAsync调用:

从Windows 10开始,在访问用户位置之前调用RequestAccessAsync。那时,你的应用程序必须在前台,RequestAccessAsync必须从UI线程调用。在用户授予你的应用程序对其位置的权限之前,你的应用程序不能访问位置数据。

来源:https://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.geolocation.geolocator.aspx?f=255&MSPPError=-2147217396