WebClient/WebRequest threading untangled

WebRequest and its baby sister WebClient behave differently regarding what thread they return on. This is a short post to really clarify what returns where.


  • WebClient will always return on the UI thread if called from the UI thread
  • WebRequest will always return on a background thread

The investigation

To test this I created a super-simple app that fetches some stuff using WebClient and WebRequest, from the UI and from a background worker.

The code:

public partial class MainPage : PhoneApplicationPage { private readonly int _uiThreadId = Thread.CurrentThread.ManagedThreadId; // Constructor public MainPage() { InitializeComponent(); } protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { WriteThreadInfo("UI"); Dispatcher.BeginInvoke(() => WriteThreadInfo("dispatcher")); RunUiRequests(); LaunchWorkerRequests(); base.OnNavigatedTo(e); } private void RunUiRequests() { var request = WebRequest.CreateHttp("http://blog.jayway.com"); request.BeginGetResponse(RequestCallbackFromUI, null); var client = new WebClient(); client.DownloadStringCompleted += client_DownloadFromUIStringCompleted; client.DownloadStringAsync(new Uri("http://blog.jayway.com", UriKind.RelativeOrAbsolute)); } private void LaunchWorkerRequests() { var worker = new BackgroundWorker(); worker.DoWork += (sender, ex) => { Thread.Sleep(2000); WriteThreadInfo("worker"); var request = WebRequest.CreateHttp("http://www.jayway.se"); request.BeginGetResponse(RequestCallbackFromWorker, null); var client = new WebClient(); client.DownloadStringCompleted += client_DownloadFromWorkerStringCompleted; client.DownloadStringAsync(new Uri("http://blog.jayway.com", UriKind.RelativeOrAbsolute)); }; worker.RunWorkerAsync(); } private void client_DownloadFromWorkerStringCompleted(object sender, DownloadStringCompletedEventArgs e) { WriteThreadInfo("webclient from worker"); } private void RequestCallbackFromWorker(IAsyncResult ar) { WriteThreadInfo("webrequest from worker"); } void client_DownloadFromUIStringCompleted(object sender, DownloadStringCompletedEventArgs e) { WriteThreadInfo("webclient from UI"); } private void RequestCallbackFromUI(IAsyncResult ar) { WriteThreadInfo("webrequest from UI"); } private void WriteThreadInfo(string threadName) { var id = Thread.CurrentThread.ManagedThreadId; Debug.WriteLine("{0,-28} Thread is {1} ({2})", threadName, id, (id == _uiThreadId) ? "UI" : "background"); } }


And one set of results from running this is:

UI                           Thread is 257753342 (UI)

dispatcher                   Thread is 257753342 (UI)

webrequest from UI           Thread is 255066402 (background)

webclient from UI            Thread is 257753342 (UI)

worker                       Thread is 254411058 (background)

webclient from worker        Thread is 236257614 (background)

webrequest from worker       Thread is 255066402 (background)

As you can see, the WebClient returns on the UI thread when called from the UI thread, but when called from the worker thread – it returns on a background thread.

I hope you feel enlightened – I do Smile


This Post Has 2 Comments

Leave a Reply