[英]Tree Hierarchy of WebClient Requests using TPL
I am developing a WPF app in C# where I have an Uri that I want to download Json data. 我正在用C#开发一个WPF应用程序,其中有一个我要下载Json数据的Uri。 The code will deserialize the downloaded Json data to object, thereafter, the object has a list of Uris that would require to request more Json data which i would like to request in parallel.
该代码会将下载的Json数据反序列化为对象,此后,该对象具有Uris列表,该列表将需要请求我想并行请求的更多Json数据。 And the downloaded Json data might have more Uris to request.
并且下载的Json数据可能需要更多Uris请求。 The code should be able to do WebClient.CancelAsync on the parent and its children's WebClient when desired.
如果需要,代码应该能够在父级及其子级的WebClient上执行WebClient.CancelAsync。 I am looking at the Task Parallel Library and finding it difficult to grasp and implement it.
我正在查看任务并行库,发现很难掌握和实现它。 I'm unsure if I should use the TPL's Cancellation token to invoke the CancelAsync or the CancelAsync to cancel the TPL's Cancellation token.
我不确定是否应该使用TPL的Cancellation令牌来调用CancelAsync或CancelCansync来取消TPL的Cancellation令牌。 And I not sure if i should use nested Tasks for the children WebClient....?
而且我不确定是否应该为孩子的WebClient使用嵌套任务。
If anyone has a similar scenario and implemented it using the new TPL.. would you mind sharing a snippet of the code... 如果有人有类似的情况并使用新的TPL来实现。.您介意共享一段代码...
Thanks. 谢谢。
If I can suggest using Reactive Extensions (Rx) on top of the TPL then this can be done quite easily without the need for cancellation tasks etc. 如果我建议在TPL之上使用Reactive Extensions(Rx) ,则可以轻松完成此操作,而无需取消任务等。
If I can assume you have the following: 如果可以假设您具有以下条件:
// 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 = ...;
Then, using Rx, you turn these functions into functions that return observables using the Task Pool, like so: 然后,使用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());
You'll need a callback to get the Uri/JSON pairs out. 您将需要回调以获取Uri / JSON对。 Something like this:
像这样:
Action<Uri, string> callback = (u, j) =>
Console.WriteLine(String.Format("{0} => {1}", u, j));
Here's the recursive LINQ query that will recursively fetch each JSON string: 这是递归的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);
Then you invoke all of this goodness using the following line: 然后,使用以下行调用所有这些好处:
var subscription = getAllUris(initialUri).Subscribe();
Now, if you want to cancel the query execution just call this: 现在,如果要取消查询执行,只需调用以下命令:
subscription.Dispose();
Rx handles all of the tasks and cancels them all for you. Rx处理所有任务并为您取消所有任务。
I hope this helps. 我希望这有帮助。
Here are the links for Rx: 这是Rx的链接:
我建议您避免创建嵌套任务,因为您无法控制正在运行的任务的数量,而是可以使用BlockingCollection使用分派模式,因为其中的工作任务数量有限,它们可以从集合中分派工作,并且可以添加如有必要,还需要做更多的工作,并且在下载所有对象时,请调用CompleteAdding以取消阻止所有等待的任务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.