问题
I am using WebClient to download some stuff from internet in Windows Phone 8.1 app. Below is the sample code i am using in my app - where i am calling below method, but my webclient is not waiting to complete the read operation and returning immediately after OpenReadAsync call.
how can i make sure that my method return operation must wait till OpenReadCompleted event is completed? I have seen multiple similar questions, but couldn't find a solution.
MyCustomObject externalObj; // my custom object
private static void CheckNetworkFile()
{
try
{
WebClient webClient = new WebClient();
webClient.OpenReadCompleted += (s, e) =>
{
externalObj = myReadWebclientResponse(e.Result); // my custom method to read the response
};
webClient.OpenReadAsync(new Uri("http://externalURl.com/sample.xml", UriKind.Absolute));
}
catch (Exception)
{
externalObj = null;
}
}
回答1:
I would advise you to use WebClient.OpenReadTaskAsync with a combination of the async/await keywords introduced in .NET 4.5 instead. You need to add the async
keyword to your method, make it return a Task
and it is advisable to end your method with the Async
postfix:
MyCustomObject externalObj;
private static async Task CheckNetworkFileAsync()
{
try
{
WebClient webClient = new WebClient();
Stream stream = await webClient.OpenReadTaskAsync(new Uri("http://externalURl.com/sample.xml", UriKind.Absolute));
externalObj = myReadWebclientResponse(stream);
}
catch (Exception)
{
externalObj = null;
}
}
Edit:
As you said, WebClient.OpenReadTaskAsync
isn't available for WP8.1, So lets create an Extension Method so it will be:
public static class WebClientExtensions
{
public static Task<Stream> OpenReadTaskAsync(this WebClient client, Uri uri)
{
var tcs = new TaskCompletionSource<Stream>();
OpenReadCompletedEventHandler openReadEventHandler = null;
openReadEventHandler = (sender, args) =>
{
try
{
tcs.SetResult(args.Result);
}
catch (Exception e)
{
tcs.SetException(e);
}
};
client.OpenReadCompleted += openReadEventHandler;
client.OpenReadAsync(uri);
return tcs.Task;
}
}
Now you can use it on your WebClient
.
You can find great reading material in the async-await wiki and by simply filtering by that tag in the search bar.
回答2:
I hope this is not too off topic, but others who are researching this might like to know that the above code sample can also be used for WCF calls in Silverlight. Be sure to add the Microsoft.Bcl.Async NuGet package first. Here is a WCF code example:
public static async Task<string> AuthenticateAsync(string userName, string password)
{
var dataAccessServiceClient = new DataAccessServiceClient("DataAccessService");
var taskCompletionSource = new TaskCompletionSource<string>();
EventHandler<AuthenticateCompletedEventArgs> completedHandler = null;
completedHandler = (s, args) =>
{
try
{
taskCompletionSource.SetResult(args.Result);
}
catch (Exception e)
{
taskCompletionSource.SetException(e);
}
};
dataAccessServiceClient.AuthenticateCompleted += completedHandler;
dataAccessServiceClient.AuthenticateAsync(userName, password);
return await taskCompletionSource.Task;
}
It can be called like this:
var result = await AuthenticateAsync(username, password);
来源:https://stackoverflow.com/questions/25051674/how-to-wait-for-webclient-openreadasync-to-complete