使用TPL的WebClient请求的树状结构
本文关键字:结构 WebClient TPL 使用 请求 | 更新日期: 2023-09-27 18:08:12
我正在c#中开发一个WPF应用程序,我有一个Uri,我想下载Json数据。代码将下载的Json数据反序列化到对象,此后,对象有一个uri列表,需要请求更多的Json数据,我想并行请求。并且下载的Json数据可能有更多uri要请求。代码应该能够做WebClient。如果需要的话,在父类和子类的WebClient上取消async。我正在看任务并行库,发现很难掌握和实现它。我不确定是否应该使用TPL的取消令牌来调用CancelAsync或CancelAsync来取消TPL的取消令牌。我不确定我是否应该使用嵌套任务的孩子WebClient....?
如果有人有类似的场景,并使用新的TPL实现它…你介意分享一段代码吗…谢谢。
如果我可以建议在TPL之上使用响应式扩展(Rx),那么这可以很容易地完成,而不需要取消任务等。
如果我可以假设你有以下内容:
// The initial Uri
Uri initialUri = ...;
// A function to return the JSON string from a given Uri
Func<Uri, string> getJason = ...;
// Turn the JSON into the next set of Uris to fetch
Func<string, IEnumerable<Uri>> getUris = ...;
然后,使用Rx,将这些函数转换为使用任务池返回可观察对象的函数,如下所示:
Func<Uri, IObservable<string>> getJasonObsFunc = u =>
Observable
.FromAsyncPattern<Uri, string>(
getJason.BeginInvoke,
getJason.EndInvoke)
.Invoke(u)
.ObserveOn(Scheduler.TaskPool);
Func<string, IObservable<Uri>> getUrisObsFunc = j =>
Observable
.FromAsyncPattern<string, IEnumerable<Uri>>(
getUris.BeginInvoke,
getUris.EndInvoke)
.Invoke(j)
.ObserveOn(Scheduler.TaskPool)
.SelectMany(xs => xs.ToObservable());
你需要一个回调来获取Uri/JSON对。像这样:
Action<Uri, string> callback = (u, j) =>
Console.WriteLine(String.Format("{0} => {1}", u, j));
下面是递归LINQ查询,它将递归地获取每个JSON字符串:
Func<Uri, IObservable<Uri>> getAllUris = null;
getAllUris = u =>
Observable
.Return<Uri>(u)
.Merge(
from j in getJasonObsFunc(u).Do(k => callback(u, k))
from u1 in getUrisObsFunc(j)
from u2 in getAllUris(u1)
select u2);
然后使用以下行调用所有这些优点:
var subscription = getAllUris(initialUri).Subscribe();
现在,如果你想取消查询执行,只需调用这个:
subscription.Dispose();
Rx处理所有的任务,并为您取消它们。
我希望这对你有帮助。
以下是Rx的链接:
- 响应式扩展论坛
- 响应扩展(Rx) v1.0.10621
我建议您避免创建嵌套任务,因为您失去了对运行任务数量的控制,相反,您可以使用调度模式使用BlockingCollection,其中有有限数量的工作任务,它们从集合中调度工作,如果有必要,它们可以添加更多的工作,当所有对象都下载后,您调用CompleteAdding来取消阻塞所有等待任务。