Rather than call WebClient.DownloadStringAsync(Uri), call the overload, DownloadString(Uri, Object), passing the Uri as the second parameter. Then, in the event handler, you can cast the value of e.UserToken to Uri to retrieve the value. That is:
Uri uri = new Uri("http://example.com");
WebClient client = new WebClient();
client.DownloadStringCompleted = StringDownloaded;
client.DownloadStringAsync(uri, uri);
void StringDownloaded(object sender, DownloadStringCompletedEventArgs e)
{
Uri uri = (Uri)e.UserToken;
...
}
You can use this technique to pass any kind of state to the event handler.