Ui连接到wifi时没有更新?

时间:2017-07-14 07:28:45

标签: c# wpf

我正在尝试使用以下代码连接到wifi:

private static bool ConnectToWifi(string profileName, WlanClient.WlanInterface wlanIface, Wifi wifi, string profile)
{
    try
    {
        wlanIface.SetProfile(Wlan.WlanProfileFlags.AllUser, profile, true);
    }
    catch (Exception e)
    {
        var ex = e;
        return false;
    };
    // Task.Run()

    wlanIface.Connect(Wlan.WlanConnectionMode.Profile, Wlan.Dot11BssType.Infrastructure, profileName);
    Thread.Sleep(5000);
    var status = wifi.ConnectionStatus;
    var x = wlanIface.GetProfileXml(profileName);
    if (status == WifiStatus.Disconnected)
    {
        return false;
    }
    return true;
}        

我保持5000毫秒的延迟以确保网络连接,但这导致我的UI在执行此代码时不显示加载图标。

如何让我的UI同时更新,而不是等待连接?

2 个答案:

答案 0 :(得分:2)

每当您在UI线程中执行Thread.Sleep时,您都会中断处理所有UI消息,这会使您的UI无响应。因此,永远不应在UI线程中执行Thread.Sleep和任何其他长时间运行的操作。

解决方案是在单独的线程中执行这些操作,以允许UI线程继续UI操作。让UI线程只进行UI操作通常是一个好主意。

在您的情况下,这意味着调用者应该在任务中执行操作:

private static bool ConnectToWifi(string profileName, WlanClient.WlanInterface wlanIface,
    Wifi wifi, string profile, Action<bool> resultCallback, Dispatcher dispatcher)
{
    //Your connect code
    bool result;
    if (status == WifiStatus.Disconnected)
    {
        result = false;
    }
    else
    {
        result = true;
    }
    dispatcher.BeginInvoke(() => resultCallback(result));
    return result;
}       

另一件事:Thread.Sleep在任务中不是一个好主意,因为你不知道你正在运行哪个调度程序。您应该使用Task.Delay代替。在这种情况下,Thread.Sleep通常不是一个好主意,因为您只是等待并希望您的任务在五秒内完成,这是无法保证的。另外,如果用户立即连接,您可能只会浪费5秒的时间。更好的解决方案是使用等待循环并定期检查连接是否已建立。如果您希望连接在相当短的时间内发生,则可以使用SpinWait.SpinUntil(超时为5秒):

SpinWait.SpinUntil(() => wifi.ConnectionStatus == WifiStatus.Connected, 5000);

答案 1 :(得分:2)

您有两种选择:

(两者都使得无法返回表示连接成功的bool而没有更多的逻辑。)

将代码移动到一个单独的线程(如果其余部分是线程安全的)并使用同步方法:

private static void ConnectToWifi(string profileName, WlanClient.WlanInterface wlanIface, Wifi wifi, string profile)
{
    new Thread(()=>{

        bool result = false;

        try
        {
            wlanIface.SetProfile(Wlan.WlanProfileFlags.AllUser, profile, true);
            wlanIface.ConnectSynchronously(Wlan.WlanConnectionMode.Profile, Wlan.Dot11BssType.Infrastructure, profileName, 5000);
            var status = wifi.ConnectionStatus;
            var x = wlanIface.GetProfileXml(profileName);

            result = (status != WifiStatus.Disconnected);
        }
        catch (Exception e)
        {
            var ex = e;
        }
        finally
        {
            Dispatcher.BeginInvoke(new Action(()=>{WhateverYouDoWithYourResult(result);}));
        }

    }).Start();
}     

或订阅WlanConnectionNotification(无法连接可能不会被视为更改,因此您必须对其进行测试):

private static bool ConnectToWifi(string profileName, WlanClient.WlanInterface wlanIface, Wifi wifi, string profile)
{
    try
    {
        wlanIface.WlanConnectionNotification += Interface_ConnectionStateChanged;
        wlanIface.SetProfile(Wlan.WlanProfileFlags.AllUser, profile, true);
        wlanIface.Connect(Wlan.WlanConnectionMode.Profile, Wlan.Dot11BssType.Infrastructure, profileName);

        return true; //Just means the attempt was successful, not the connecting itself
    }
    catch (Exception e)
    {
        var ex = e;
        return false;
    }
}     

private static void Interface_ConnectionStateChanged(Wlan.WlanNotificationData notifyData, Wlan.WlanConnectionNotificationData connNotifyData)
{
    // Do something with that info, be careful - might not be the same thread as before.
}

我现在无法访问Wifi,所以我还没有对代码进行测试。它应该可以工作,但你最好把它看作伪代码而不是实际的现成解决方案。