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.
Summary
- 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://www.jayway.com");
request.BeginGetResponse(RequestCallbackFromUI, null);
var client = new WebClient();
client.DownloadStringCompleted += client_DownloadFromUIStringCompleted;
client.DownloadStringAsync(new Uri("http://www.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://www.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 ![]()
Andreas Hammar
Consultant at Jayway

0 comments ↓
There are no comments yet...Kick things off by filling out the form below.
Leave a Comment