Reputation: 3413
I made a function like this:
public void GetData(string dataToPost)
{
var url = "some URL";
using (var client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "application/json";
client.UploadStringCompleted += (s, e) =>
{
Console.WriteLine("Result is here");
Console.WriteLine(e.Result);
};
client.UploadStringAsync(new System.Uri(url), "POST", dataToPost);
}
}
The problem here is the fact that I want to get a value returned from the server (HTTP response).
I want my function to be asynchronous, so for example I'd like to be able to call it 5 times in a loop, without waiting for each call to return something before next call.
I have no idea how to achieve it. I tried to create some Task object to await it, but Task requires a delegate and I don't know what delegate i could give it.
Te function above uses an event, which is fired when the result comes - so I need to return that result.
How can I do that?
Upvotes: 0
Views: 154
Reputation: 28355
As already been said in comments, HttpClient
is more natural choice for such tasks. However, you still may wonder how to provide a task subscribed for an event, and that could be done with TaskCompletionSource<T>
, with quite small changes to your code:
private Task<string> GetData(string dataToPost)
{
var url = "some URL";
var resultSource = new TaskCompletionSource<string>();
using (var client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "application/json";
client.UploadStringCompleted += (s, e) => {
Console.WriteLine("Result is here");
Console.WriteLine(e.Result);
// this will complete the task
resultSource.SetResult(e.Result);
};
client.UploadStringAsync(new System.Uri(url), "POST", dataToPost);
}
return resultSource.Task;
}
You can also set a cancellation (with a given token too) and exception (even with multiple exceptions) in this case, so it will naturally fit to your needs. All three methods can be done in Try*
fashion for the cases of concurrent event subscription.
Also note the @Stefanod'Antonio' answer for an async
method overload.
Upvotes: 1
Reputation: 6152
WebClient
has an overload that returns a Task<string>
:
https://msdn.microsoft.com/en-us/library/hh193920(v=vs.110).aspx
You can fire all your requests and then wait for them with Task.WhenAll
:
public void GetData(string dataToPost)
{
var url = "some URL";
var url2 = "some other URL";
using (var client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "application/json";
var task1 = client.UploadStringTaskAsync(new System.Uri(url), "POST", dataToPost);
var task2 = client.UploadStringTaskAsync(new System.Uri(url2), "POST", dataToPost);
var results = Task.WhenAll(task1, task2).Result;
foreach (var result in results)
{
Console.WriteLine("Result is here");
Console.WriteLine(result);
}
}
}
Even better if you can change your GetData to be an async
method, you can just await
on Task.WhenAll
Upvotes: 2