我的实际程序比这更复杂,但我试图简化事情。
假设我正在读取一个包含 URL 列表的文件。我想从每个 URL 下载 HTML 并处理它。处理可能有点复杂,所以我希望它在一个单独的线程上完成。
基本问题是如何判断所有处理何时完成。例如,如果用户试图在处理所有 URL 之前关闭程序,我想给他一条消息而不退出程序。或者,我想在处理完所有 URL 后立即终止程序(可能使用 MsgBox("Done") 消息)。
我希望我的代码如下所示(假设我有一个外部循环读取 URL 并调用此例程)...
List<Task> TaskList = new List<Task>();
async void ProcessSingleUrl(string url) {
var web = new HttpClient();
var WebPageContents = await web.GetStringAsync(url);
Task t = Task.Run(() => ProcessWebPage(WebPageContents);
TaskList.Add(t);
}
上面的代码应该运行得非常快(异步方法立即运行得很好)并且几乎立即返回给调用者。
但是到那时,我很可能在 TaskList 中没有任何条目,因为在 GetStringAsync 完成之前没有定义任务,并且到那时可能没有(或者可能只有少数)完成。所以
Task.WaitAll(TaskList.ToArray());
不能按我需要的方式工作。
如果绝对有必要,我可以先阅读所有 URL 并知道预期有多少任务,但我希望有一个更优雅的解决方案。
我想我可以在等待之前增加一个计数器,但这感觉有点笨拙。
我认为我的结构不正确,但我不确定如何重组。
注意:我不喜欢 Task.Run。Good ol' QueueWorkItem 是一种可能性,但我认为它也有同样的问题。