Reading NetworkInterfaceType can take over 20 seconds!
We
have an app where we need to determine whether the phone has an
internet connection, and whether it is on WiFi or cellular. We do this
step when the app launches or whenever it reactivates after tombstoning.
To determine the type of connection, we use , as in:
using Microsoft.Phone.Net.NetworkInformation; |
|
NetworkInterfaceType currentInterface = NetworkInterface.NetworkInterfaceType; |
NetworkInterfaceType is an enum that identifies the connection type: WiFi, Ethernet (via USB to a PC), cellular or none.
We
were running into an issue where the app was taking a long time start
up or reactivate, sometimes so long that the system closed the app (I
believe because the system thinks it became unresponsive). I narrowed it
down to the statement that accessed NetworkInterface.NetworkInterfaceType.
I tested and found that executing that single statement could take
anywhere from 0.3 seconds to 23 seconds! The same behavior was
repeatable on the Samsung Focus and the developer LG Pacific.
I
had put the statement in the UI thread because I
thought NetworkInterfaceType is a value that would be returned
immediately. So the single statement was sometimes hanging up the UI for
a very long time. My workaround was to retrieve NetworkInterfaceType in
a worker thread and check the value later.
Below
is my test app to measure response time. If you click on the
NetworkInterfaceType button, it will display the returned value and how
long it took. Here I'm using a worker thread as I do in our product app,
but I saw no difference if NetworkInterfaceType is retrieved directly
in the click handler.
MainPage.xaml
<phone:PhoneApplicationPage |
x:Class="NetworkStatus.MainPage" |
xmlns="" |
xmlns:x="" |
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" |
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" |
xmlns:d="" |
xmlns:mc="" |
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" |
FontFamily="{StaticResource PhoneFontFamilyNormal}" |
FontSize="{StaticResource PhoneFontSizeNormal}" |
Foreground="{StaticResource PhoneForegroundBrush}" |
SupportedOrientations="Portrait" Orientation="Portrait" |
shell:SystemTray.IsVisible="True"> |
|
|
<Grid x:Name="LayoutRoot" Background="Transparent"> |
<Grid.RowDefinitions> |
<RowDefinition Height="Auto"/> |
<RowDefinition Height="*"/> |
Grid.RowDefinitions> |
|
|
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> |
<TextBlock x:Name="ApplicationTitle" Text="NETWORK STATUS" Style="{StaticResource PhoneTextNormalStyle}"/> |
<TextBlock x:Name="PageTitle" Text="api timing" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> |
StackPanel> |
|
|
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> |
<StackPanel VerticalAlignment="Center"> |
<TextBlock x:Name="GetIsNetworkAvailableText" Height="34" HorizontalAlignment="Center" FontSize="24"/> |
<Button x:Name="GetIsNetworkAvailableButton" Content="GetIsNetworkAvailable()" Margin="0,0,0,40" Click="GetIsNetworkAvailableButton_Click"/> |
<TextBlock x:Name="NetworkInterfaceTypeText" Height="34" HorizontalAlignment="Center" FontSize="24"/> |
<Button x:Name="NetworkInterfaceTypeButton" Content="NetworkInterfaceType" Click="NetworkInterfaceTypeButton_Click"/> |
StackPanel> |
Grid> |
Grid> |
|
phone:PhoneApplicationPage> |
MainPage.xaml.cs
using System; |
using System.Windows; |
using Microsoft.Phone.Controls; |
using System.ComponentModel; |
using Microsoft.Phone.Net.NetworkInformation; |
|
namespace NetworkStatus |
{ |
public partial class MainPage : PhoneApplicationPage |
{ |
BackgroundWorker networkAvailableWorker; |
BackgroundWorker interfaceTypeWorker; |
NetworkInterfaceType netType; |
bool isNetworkAvailable; |
TimeSpan typeResponseTime; |
TimeSpan availableResponseTime; |
|
// Constructor |
public MainPage() |
{ |
InitializeComponent(); |
|
networkAvailableWorker = new BackgroundWorker(); |
networkAvailableWorker.DoWork += new DoWorkEventHandler(networkAvailableWorker_DoWork); |
networkAvailableWorker.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(networkAvailableWorker_RunWorkerCompleted); |
|
interfaceTypeWorker = new BackgroundWorker(); |
interfaceTypeWorker.DoWork += new DoWorkEventHandler(interfaceTypeWorker_DoWork); |
interfaceTypeWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(interfaceTypeWorker_RunWorkerCompleted); |
} |
|
private void GetIsNetworkAvailableButton_Click(object sender, RoutedEventArgs e) |
{ |
GetIsNetworkAvailableText.Text = "waiting..."; |
GetIsNetworkAvailableButton.IsEnabled = false; |
networkAvailableWorker.RunWorkerAsync(); |
} |
|
void networkAvailableWorker_DoWork(object sender, DoWorkEventArgs e) |
{ |
DateTime beginTime = DateTime.UtcNow; |
isNetworkAvailable = NetworkInterface.GetIsNetworkAvailable(); |
availableResponseTime = DateTime.UtcNow - beginTime; |
} |
|
void networkAvailableWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) |
{ |
GetIsNetworkAvailableText.Text = isNetworkAvailable.ToString() + String.Format(" ({0}s)", availableResponseTime.TotalMilliseconds/1000.0); |
GetIsNetworkAvailableButton.IsEnabled = true; |
} |
|
private void NetworkInterfaceTypeButton_Click(object sender, RoutedEventArgs e) |
{ |
NetworkInterfaceTypeText.Text = "waiting..."; |
NetworkInterfaceTypeButton.IsEnabled = false; |
interfaceTypeWorker.RunWorkerAsync(); |
} |
|
void interfaceTypeWorker_DoWork(object sender, DoWorkEventArgs e) |
{ |
DateTime beginTime = DateTime.UtcNow; |
netType = NetworkInterface.NetworkInterfaceType; |
typeResponseTime = DateTime.UtcNow - beginTime; |
} |
|
void interfaceTypeWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) |
{ |
NetworkInterfaceTypeText.Text = netType.ToString() + String.Format(" ({0}s)", typeResponseTime.TotalMilliseconds/1000.0); |
NetworkInterfaceTypeButton.IsEnabled = true; |
} |
|
} |
} |
I
found that when the phone was connected on WiFi or
USB, NetworkInterfaceType would usually return in less than half a
second. However on cellular connection there were huge variations. 2-3
seconds was typical while in good cellular coverage. The reponse may
drop to half a second after repeating the operation, but may go back up
just a few moments later. Under marginal cellular coverage, the time can
vary from a couple of seconds up to over 20 seconds (worst I saw was 23
sec).
This
suggests that it is performing some kind of ping test and the slow
response comes from actual internet delay. However, all I want to know
is what type of network the phone is currently using. Isn't that always
known by the phone and should give an instantaneous result? Using a
worker thread helped, but our UI needs to do different actions depending
on WiFi/cellular and it is a burden needing to handle a result that may
not return for 20 seconds.
阅读(1227) | 评论(0) | 转发(0) |