/// <summary>
        /// Asynchronously attempts to connect to the wireless LAN associated to a specified wireless profile.
        /// </summary>
        /// <param name="interfaceId">Interface ID</param>
        /// <param name="profileName">Profile name</param>
        /// <param name="bssType">BSS network type</param>
        /// <param name="timeout">Timeout duration</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>True if successfully connected. False if failed or timed out.</returns>
        public static async Task <bool> ConnectNetworkAsync(Guid interfaceId, string profileName, BssType bssType, TimeSpan timeout, CancellationToken cancellationToken)
        {
            if (interfaceId == Guid.Empty)
            {
                throw new ArgumentException(nameof(interfaceId));
            }

            if (string.IsNullOrWhiteSpace(profileName))
            {
                throw new ArgumentNullException(nameof(profileName));
            }

            if (timeout < TimeSpan.Zero)
            {
                throw new ArgumentException(nameof(timeout));
            }

            using (var client = new Base.WlanClient())
            {
                var tcs = new TaskCompletionSource <bool>();

                Action <IntPtr, IntPtr> callback = (data, context) =>
                {
                    var notificationData = Marshal.PtrToStructure <WLAN_NOTIFICATION_DATA>(data);
                    if (notificationData.NotificationSource != WLAN_NOTIFICATION_SOURCE_ACM)
                    {
                        return;
                    }

                    Debug.WriteLine("Callback: {0}", (WLAN_NOTIFICATION_ACM)notificationData.NotificationCode);

                    switch (notificationData.NotificationCode)
                    {
                    case (uint)WLAN_NOTIFICATION_ACM.wlan_notification_acm_connection_complete:
                        Task.Run(() => tcs.SetResult(true));
                        break;

                    case (uint)WLAN_NOTIFICATION_ACM.wlan_notification_acm_connection_attempt_fail:
                        Task.Run(() => tcs.SetResult(false));
                        break;
                    }
                };

                Base.RegisterNotification(client.Handle, WLAN_NOTIFICATION_SOURCE_ACM, callback);

                var result = Base.Connect(client.Handle, interfaceId, profileName, ConvertFromBssType(bssType));
                if (!result)
                {
                    tcs.SetResult(false);
                }

                var connectTask   = tcs.Task;
                var completedTask = await Task.WhenAny(connectTask, Task.Delay(timeout, cancellationToken));

                return((completedTask == connectTask) && connectTask.Result);
            }
        }
        /// <summary>
        /// Asynchronously requests wireless interfaces to scan (rescan) wireless LANs.
        /// </summary>
        /// <param name="timeout">Timeout duration</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Interface IDs that successfully scanned</returns>
        public static async Task <IEnumerable <Guid> > ScanNetworksAsync(TimeSpan timeout, CancellationToken cancellationToken)
        {
            using (var client = new Base.WlanClient())
            {
                var interfaceInfoList = Base.GetInterfaceInfoList(client.Handle);
                var interfaceIds      = interfaceInfoList.Select(x => x.InterfaceGuid).ToArray();

                var tcs     = new TaskCompletionSource <bool>();
                var handler = new ScanHandler(tcs, interfaceIds);

                Action <IntPtr, IntPtr> callback = (data, context) =>
                {
                    var notificationData = Marshal.PtrToStructure <WLAN_NOTIFICATION_DATA>(data);
                    if (notificationData.NotificationSource != WLAN_NOTIFICATION_SOURCE_ACM)
                    {
                        return;
                    }

                    Debug.WriteLine("Callback: {0}", (WLAN_NOTIFICATION_ACM)notificationData.NotificationCode);

                    switch (notificationData.NotificationCode)
                    {
                    case (uint)WLAN_NOTIFICATION_ACM.wlan_notification_acm_scan_complete:
                        handler.SetSuccess(notificationData.InterfaceGuid);
                        break;

                    case (uint)WLAN_NOTIFICATION_ACM.wlan_notification_acm_scan_fail:
                        handler.SetFailure(notificationData.InterfaceGuid);
                        break;
                    }
                };

                Base.RegisterNotification(client.Handle, WLAN_NOTIFICATION_SOURCE_ACM, callback);

                foreach (var interfaceId in interfaceIds)
                {
                    var result = Base.Scan(client.Handle, interfaceId);
                    if (!result)
                    {
                        handler.SetFailure(interfaceId);
                    }
                }

                var scanTask = tcs.Task;
                await Task.WhenAny(scanTask, Task.Delay(timeout, cancellationToken));

                return(handler.Results);
            }
        }