完成c#任务再次运行……为什么?
发布时间:2020-12-15 23:28:56 所属栏目:百科 来源:网络整理
导读:我对我的代码[下面]的行为感到有点困惑.我正在开发一个专门的命令行实用程序,可以下载和处理一些文件.我想尽可能使用c#的异步功能.创建任务并使用Task.WaitAll()时,代码段按预期运行.在等待之后,我有2个任务,这两个任务都被标记为已完成.问题:我尝试从任务
我对我的代码[下面]的行为感到有点困惑.我正在开发一个专门的命令行实用程序,可以下载和处理一些文件.我想尽可能使用c#的异步功能.创建任务并使用Task.WaitAll()时,代码段按预期运行.在等待之后,我有2个任务,这两个任务都被标记为已完成.问题:我尝试从任务中获取结果最终会再次运行这两个任务!为什么是这样?如何在不执行第二次任务的情况下读取结果?
private IEnumerable<Task<FileInfo>> DownloadFiles() { int fileCount = 1; Console.Clear(); Console.SetCursorPosition(0,0); Console.Write("Download files..."); yield return DownloadFile(Options.SkuLookupUrl,"SkuLookup.txt.gz",fileCount++,f => { return DecompressFile(f); }); yield return DownloadFile(Options.ProductLookupUrl,"ProductList.txt.gz",f => { return DecompressFile(f); }); } public void Execute() { var tasks = DownloadFiles(); Task.WaitAll(tasks.ToArray()); Console.WriteLine(); Console.WriteLine("Download(s) completed. Parsing sku lookup file."); FileInfo[] files = tasks.Select(t => t.Result).ToArray(); // <-- triggers a second round of task execution ParseSkuLookups(files.SingleOrDefault(f => f.Name.ToLowerInvariant().Contains("skulookup"))); } 如果相关的是下载方法: private async Task<FileInfo> DownloadFile(string targetUrl,string destinationFile,int lineNumber,Func<FileInfo,FileInfo> callback = null) { FileInfo fi = new FileInfo(destinationFile); if (!Options.NoCleanup || !fi.Exists) { WebClient client = new WebClient(); client.DownloadProgressChanged += (s,e) => { char spinnerChar; switch ((e.ProgressPercentage % 10)) { case 0: spinnerChar = '|'; break; case 1: spinnerChar = '/'; break; case 2: spinnerChar = '-'; break; case 3: spinnerChar = '|'; break; case 4: spinnerChar = ''; break; case 5: spinnerChar = '|'; break; case 6: spinnerChar = '/'; break; case 7: spinnerChar = '-'; break; case 8: spinnerChar = ''; break; default: case 9: spinnerChar = '|'; break; } lock (ConsoleLockSync) { Console.SetCursorPosition(0,lineNumber); Console.WriteLine(String.Format("{0} download: {1}% {2}",destinationFile,e.ProgressPercentage==100 ? "[Complete]" : spinnerChar.ToString())); } }; await client.DownloadFileTaskAsync(new Uri(targetUrl,UriKind.Absolute),destinationFile); } else if(Options.NoCleanup) { lock (ConsoleLockSync) { Console.SetCursorPosition(0,lineNumber); Console.WriteLine(String.Format("{0} download: Skipped [No Cleanup] ",destinationFile)); } } fi.Refresh(); return callback != null ? callback(fi) : fi; } 解决方法
如果每次枚举结果时都有一个带有yield返回值的IEnumerable,它将重新运行你的函数. task.WaitAll中的tasks.ToArray()(tasks.ToArray());枚举它然后再在任务中枚举它.选择(t => t.Result).ToArray();.要使其枚举,请保留第一个ToArray()调用的结果,然后在整个方法中重复使用该结果.
public void Execute() { var tasks = DownloadFiles(); var taskArray = tasks.ToArray(); Task.WaitAll(taskArray); Console.WriteLine(); Console.WriteLine("Download(s) completed. Parsing sku lookup file."); FileInfo[] files = taskArray.Select(t => t.Result).ToArray(); // <-- notice we use taskArray here instead of tasks. ParseSkuLookups(files.SingleOrDefault(f => f.Name.ToLowerInvariant().Contains("skulookup"))); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |