Windows Mobile Developer Center > Windows Phone Forums > Windows Phone 7 > WebClient, HttpWebRequest and the UI Thread on Windows Phone 7

Locked WebClient, HttpWebRequest and the UI Thread on Windows Phone 7

  • Saturday, September 25, 2010 2:33 AM
     
     

    Following is code you can paste into a new Windows Phone Application project which demonstrates why using WebClient to do non trivial operations has a negative impact on your user interface as first discovered on the phone platform in this thread.

    What this project demonstrates is that WebClient callbacks are running on the UI thread on the phone platform thus alleviating the need to use the dispatcher to update the UI. The code also demonstrates the need to utilise the dispatcher to update the UI from HttpWebRequest callbacks.

    The takeaway here is to use HttpWebRequest for any heavy lifting.

    • Edited by Mick N Saturday, September 25, 2010 2:54 AM title revision
    •  

All Replies

  • Saturday, September 25, 2010 2:40 AM
     
     
    Am I too quick for the code?
  • Saturday, September 25, 2010 2:40 AM
     
      Has Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using Microsoft.Phone.Controls;
    using System.IO;
    
    namespace WebClientHttpWebRequest
    {
      public partial class MainPage : PhoneApplicationPage
      {
        // Constructor
        public MainPage()
        {
          InitializeComponent();
        }
    
        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
          DoWebClient();
          DoHttpWebRequest();
        }
    
    
    
        private void DoWebClient()
        {
          var webClient = new WebClient();
    
          webClient.OpenReadAsync(new Uri("http://www.bing.com"));
          webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
    
        }
    
        void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
    
          using (var reader = new StreamReader(e.Result))
          {
            webClientTextBlock.Text = reader.ReadToEnd(); 
          }
    
        }
    
    
    
    
        private void DoHttpWebRequest()
        {
          string url = "http://www.bing.com";
    
          var request = HttpWebRequest.Create(url);
          var result = (IAsyncResult)request.BeginGetResponse(ResponseCallback, request);
        }
    
        private void ResponseCallback(IAsyncResult result)
        {
          var request = (HttpWebRequest)result.AsyncState;
          var response = request.EndGetResponse(result);
    
          using (var stream = response.GetResponseStream())
          using (var reader = new StreamReader(stream))
          {
            // FAIL - httpWebRequestTextBlock.Text = reader.ReadToEnd(); //UnauthorizedAccessException was Unhandled - Invalid cross-thread access.
    
            // FAIL - Dispatcher.BeginInvoke(() => { httpWebRequestTextBlock.Text = reader.ReadToEnd(); }); //ObjectDisposedException unhandled - Cannot read from a closed TextReader.
    
            var contents = reader.ReadToEnd();
            Dispatcher.BeginInvoke(() => { httpWebRequestTextBlock.Text = contents; });
    
          }
        }
    
      }
    }
    
  • Saturday, September 25, 2010 2:40 AM
     
      Has Code
    <phone:PhoneApplicationPage 
      x:Class="WebClientHttpWebRequest.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
      xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      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" Loaded="PhoneApplicationPage_Loaded">
    
      <!--LayoutRoot is the root grid where all page content is placed-->
      <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
    
        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
          <TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
          <TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>
    
        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
          <TextBlock Height="254" HorizontalAlignment="Left" Margin="12,6,0,0" Name="webClientTextBlock" Text="TextBlock" VerticalAlignment="Top" Width="438" />
          <TextBlock Height="254" HorizontalAlignment="Left" Margin="9,266,0,0" Name="httpWebRequestTextBlock" Text="TextBlock" VerticalAlignment="Top" Width="438" />
        </Grid>
      </Grid>
     
      <!--Sample code showing usage of ApplicationBar-->
      <!--<phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
          <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/>
          <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/>
          <shell:ApplicationBar.MenuItems>
            <shell:ApplicationBarMenuItem Text="MenuItem 1"/>
            <shell:ApplicationBarMenuItem Text="MenuItem 2"/>
          </shell:ApplicationBar.MenuItems>
        </shell:ApplicationBar>
      </phone:PhoneApplicationPage.ApplicationBar>-->
    
    </phone:PhoneApplicationPage>
    
  • Saturday, September 25, 2010 2:45 AM
     
     

    Other than this performance consideration, WebClient utilises HttpWebRequest internally to provide a simpler and easier to use interface and as such can be used when it meets your needs.

    WebClient's interface does simplify coding and as a result does not have all the flexibility of HttpWebRequest. In some cases WebClient will not meed your needs and then it is only a little more work to put HttpWebRequest to the task.

  • Saturday, September 25, 2010 2:46 AM
     
     
    Am I too quick for the code?

    lol Steve, yes !! ;p