我有一个名为WebUtil
的类,其中有一个名为GetWebpage()
的抽象函数。在这个函数的一个实现中,我使用WebClient
类,在另一个实现中我使用新的HttpClient
及其await / async功能。问题是使用HttpClient
要求方法返回Task<>
,所以我改变了抽象方法定义。但是现在使用WebClient
的函数也必须返回Task<>
。
有没有一个好方法来处理这个问题?有什么我不熟悉的吗?
答案 0 :(得分:3)
您可以使用Task<>
WebClient
返回Task.FromResult
。
Task<string> GetWebPage(string url)
{
var c = new WebClient();
var html = c.DownloadString(url);
return Task.FromResult(html);
}
或者,您可以使用TaskCompleteSource<T>
将事件转换为任务:
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;
}
答案 1 :(得分:1)
你必须坚持使用其中一个。就个人而言,我会选择异步并重写使用WebClient返回任务的覆盖。在功能方面,您将获得更多收益(例如,请参阅CancellationToken支持的代码段)。由于此方法的非阻塞性质,这也恰好是更好的设计。
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;
}
答案 2 :(得分:0)
正如Stephen Cleary在评论中提到的,WebClient
也支持async
,因此您只需调用其中一种-TaskAsync
方法。
但总的来说,使用async
(如果方法很快)或Task.FromResult()
(如果它很慢)实现Task.Run()
接口是可以的。