Reputation: 3414
I have a class called WebUtil
and in it is an abstract function called GetWebpage()
. In one implementation of this function I use the WebClient
class, in another I use the new HttpClient
with its await/async functionality. Problem is the use of HttpClient
requires the method to return Task<>
, so I changed the abstract method definition. But now the function that uses the WebClient
has to also return Task<>
.
Is there a good way to handle this? Is there something I'm not familiar with?
Upvotes: 0
Views: 315
Reputation: 244968
As Stephen Cleary mentioned in a comment, WebClient
does support async
too, so you can just call one of the -TaskAsync
methods.
But in general, it's okay to implement async
interface using either Task.FromResult()
(if the method is fast), or Task.Run()
(if it's slow).
Upvotes: 0
Reputation: 9587
You will have to stick with one or the other. Personally, I would pick async and rework the override which uses WebClient to return a Task. You will get more bang for your buck in terms of functionality (see the code snippet for CancellationToken support, for example). This also happens to be a better design due the non-blocking nature of this method.
public override Task<string> GetWebpage(CancellationToken cancellationToken)
{
var client = new WebClient();
var tcs = new TaskCompletionSource<string>();
client.DownloadStringCompleted += (sender, e) =>
{
if (e.Cancelled)
{
tcs.SetCanceled();
}
else if (e.Error != null)
{
tcs.SetException(e.Error);
}
else
{
tcs.SetResult(e.Result);
}
};
client.DownloadStringAsync(this.Url);
if (cancellationToken.CanBeCanceled)
{
cancellationToken.Register(client.CancelAsync);
}
return tcs.Task;
}
Upvotes: 1
Reputation: 10544
You can return Task<>
with the WebClient
with Task.FromResult
.
Task<string> GetWebPage(string url)
{
var c = new WebClient();
var html = c.DownloadString(url);
return Task.FromResult(html);
}
Or, you can use TaskCompleteSource<T>
convert events to task:
Task<string> GetWebPage(string url)
{
var c = new WebClient();
var tcs = new TaskCompleteSource<string>();
c.DownloadStringCompleted += (o, e) => tcs.SetResult((string)e.Result);
c.DownloadStringAsync(new Uri(url));
return tcs.Task;
}
Upvotes: 3