TPL DataFlow代码未执行预期下载及保存逻辑的问题求助
问题描述
参考文章编写了如下C# TPL DataFlow代码:
using System; using System.Net; using System.Threading.Tasks.Dataflow; using System.Collections.Generic; public class Program { public static void Main() { var fetchImageFlag = new TransformBlock<string, (string, byte[])>( async urlImage => { Console.WriteLine($"Downloading {urlImage}"); using var webClient = new WebClient(); var data = await webClient.DownloadDataTaskAsync(urlImage); return (urlImage, data); }); var saveData = new ActionBlock<(string, byte[])>(data => { (string urlImage, byte[] image) = data; Console.WriteLine($"==> UrlImage: {urlImage}"); }); fetchImageFlag.LinkTo(saveData); List<string> urlFlags = new List<string>{ "Italy#/media/File:Flag_of_Italy.svg", "Spain#/media/File:Flag_of_Spain.svg", "United_States#/media/File:Flag_of_the_United_States.svg" }; foreach (var urlFlag in urlFlags) { Console.WriteLine($"Calling: {urlFlag}"); fetchImageFlag.Post($"https://en.wikipedia.org/wiki/{urlFlag}"); } } }
运行后仅输出:
Calling: Italy#/media/File:Flag_of_Italy.svg Calling: Spain#/media/File:Flag_of_Spain.svg Calling: United_States#/media/File:Flag_of_the_United_States.svg
未出现预期的"Downloading {File}"和"==> UrlImage: {urlImage}"相关输出,请问问题出在哪里?
问题原因与解决方案
问题核心是主线程提前退出:TPL DataFlow的块默认使用后台线程执行任务,当Main方法执行完foreach循环后,主线程直接结束,整个进程随之终止,后台的下载和处理任务根本没机会运行。
解决方法如下:
方法1:异步等待所有任务完成
修改Main方法为异步签名,标记数据块不再接收新数据后,等待处理块完成所有任务:
public static async Task Main() { // ... 原有代码保持不变 ... foreach (var urlFlag in urlFlags) { Console.WriteLine($"Calling: {urlFlag}"); fetchImageFlag.Post($"https://en.wikipedia.org/wiki/{urlFlag}"); } // 标记fetchImageFlag不再接受新数据 fetchImageFlag.Complete(); // 等待saveData处理完所有数据 await saveData.Completion; }
方法2:阻塞主线程等待(非异步场景)
如果不想修改Main方法签名,可直接阻塞主线程等待处理完成:
// ... 原有代码保持不变 ... foreach (var urlFlag in urlFlags) { Console.WriteLine($"Calling: {urlFlag}"); fetchImageFlag.Post($"https://en.wikipedia.org/wiki/{urlFlag}"); } fetchImageFlag.Complete(); // 阻塞主线程直到saveData处理完成 saveData.Completion.Wait();
额外提示:当前构造的URL格式不正确,维基百科媒体文件的直接下载地址并非页面URL,后续需要修正URL才能真正下载到图片,但这不是本次无输出的原因。
内容的提问来源于stack exchange,提问作者DavidS
相关产品推荐
相关产品推荐

