C#中的循环异步任务列表我正在尝试不断地解析来自多个网站的数据。我想在一个循环中异步地单独执行此操作,直到程序关闭。我不确定这个逻辑应该如何构建。现在我正在遵循这种模式。asyncpublicvoidParseAll(ListSiteList){ListTaskList=newList();foreach(SiteList中的Sites){TaskList.Add(s.ParseData);}awaitTask.WhenAll(TaskList)}问题是如果我绕过这个方法构造一个循环,那么首先更新的站点必须等到整个列表完成才能再次运行该方法。理论上,我想做的就是在ParseData方法完成后将每个站点放回TaskList的底部,但我不确定这是否可行,或者这是否是最好的方法。从理论上讲,我想做的就是在ParseData完成后将每个站点放回TaskList的底部。看起来您需要维护要处理的站点队列。这是我的看法,使用SemaphoreSlim。这样,您还可以将并发任务的数量限制为少于实际站数,或者即时添加新站。CancellationToken用于停止外部处理。在这里使用asyncvoid是合理的,IMO,QueueSiteAsync跟踪它启动的任务。使用系统;使用System.Collections.Generic;使用System.Linq;使用系统线程;使用System.Threading.Tasks;namespaceAsyncLoop{classProgram{publicclassSite{publicstringUrl{get;放;}publicasyncTaskParseDataAsync(CancellationTokentoken){//模拟下载和解析intdelay=newRandom(Environment.TickCount).Next(100,1000);等待任务。延迟(延迟,令牌);Console.WriteLine("处理:#{0},延迟:{1}",this.Url,delay);}}object_lock=newObject();HashSet_pending=newHashSet();//正在进行的站点SemaphoreSlim_semaphore;asyncvoidQueueSiteAsync(Sitesite,CancellationTokentoken){FuncprocessSiteAsync=async()=>{await_semaphore.WaitAsync(token).ConfigureAwait(false);尝试{awaitsite.ParseDataAsync(token);QueueSiteAsync(网站,令牌);}最后{_semaphore.Release();}};vartask=processSiteAsync();锁(_lock)_pending.Add(任务);尝试{等待任务;锁(_lock)_pending.Remove(task);}catch{if(!task.IsCanceled&&!task.IsFaulted)抛出;//非任务错误,重新抛出//将故障任务留在待处理列表中并退出//ProcessAllSites将拾取它}}publicasyncTaskProcessAllSites(Site[]sites,intmaxParallel,CancellationTokentoken){_semaphore=新的SemaphoreSlim(Math.Min(sites.Length,maxParallel));//启动所有站点foreach(varsiteinsites)QueueSiteAsync(site,token);//等待取消try{awaitTask.Delay(Timeout.Infinite,token);}catch(OperationCanceledException){}//等待挂起的任务Task[]tasks;锁(_lock)任务=_pending.ToArray();等待Task.WhenAll(任务);}//测试staticvoidMain(string[]args){//在10秒内取消处理varcts=newCancellationTokenSource(millisecondsDelay:10000);varsites=Enumerable.Range(0,count:10).Select(i=>newSite{Url=i.ToString()});尝试{newProgram().ProcessAllSites(sites.ToArray(),maxParallel:5,token:cts.令牌).等待();}catch(AggregateExceptionex){foreach(varinnerExinex.InnerExceptions)Console.WriteLine(innerEx.Message);}}}}您可能还想将下载和解析分开到单独的管道中,请查看此以获取更多详细信息。很容易创建一个循环连续循环并一遍又一遍地解析单个站点的方法。一旦你有了这个方法,你就可以在列表中的每个站点上调用它一次:privateasyncvoidParseSite(Sites){while(true){awaits.ParseData();}}publicvoidParseAll(ListsiteList){foreach(varsiteinsiteList){ParseSite(site);如果你想在完成后再次访问该站点,你可能想使用Task.WhenAny并将你的外部循环与你的内部循环集成,就像这样(假设ParseData函数将返回它正在解析的站点):asyncpublicvoidParseAll(ListSiteList){while(true){List>TaskList=newList>();foreach(SiteList中的Sites){TaskList.Add(s.ParseData());}awaitTask.WhenAny(TaskList);TaskList=TaskList.Select(t=>t.IsCompleted?t.Result.ParseData():t).ToList();你试过PLinqlib吗?Plinq允许您异步执行linq查询。在您的情况下,它看起来像:SiteList.AsParallel()。ForEach(s=>s.ParseData);以上就是《C#学习教程:C#循环异步任务列表》的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多加关注——本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
