0

我有一个名为的类WebUtil,其中有一个名为GetWebpage(). 在这个函数的一个实现中,我使用WebClient类,在另一个实现中,我使用HttpClient带有等待/异步功能的新类。问题是使用HttpClient需要返回的方法Task<>,所以我更改了抽象方法定义。但是现在使用 的函数WebClient也必须 return Task<>

有没有好的方法来处理这个?有什么我不熟悉的吗?

4

3 回答 3

3

您可以Task<>使用WebClientwith返回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;
}
于 2013-06-01T11:12:25.457 回答
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;
    }
于 2013-06-01T11:17:13.520 回答
0

正如 Stephen Cleary 在评论中提到的那样,WebClient它也支持async,所以你可以调用其中一种-TaskAsync方法。

但总的来说,async使用Task.FromResult()(如果方法快)或Task.Run()(如果方法慢)实现接口是可以的。

于 2013-06-01T13:27:57.733 回答