我的实际程序比这更复杂,但我试图简化的东西。异步/等待和Task.Run - 如何知道什么时候完成
因此,让我们说我正在阅读一个URL列表的文件。我想从每个URL下载HTML并处理它。处理过程可能有点复杂,所以我希望它在单独的线程上完成。
基本问题是如何判断何时完成所有处理。例如,如果用户试图在处理所有URL之前关闭该程序,我想给他一条消息而不是退出程序。或者,我希望在处理所有URL后终止程序(也许带有MsgBox(“完成”)消息)。
我想我的代码看起来如下(假设我有一个外循环读取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());
不按我需要的方式工作。
如果绝对必要,我可以先阅读所有网址,并知道需要多少任务,但我希望有一个更优雅的解决方案。
我想我可以在等待之前增加一个计数器,但这感觉有点遗憾。
我假设我正在构造错误的东西,但我不知道如何重组事情。
注意:我没有执着于Task.Run。好的'QueueWorkItem是一种可能性,但我认为它也有相同的问题。
在我看来,这是行不通的。 –
在我看来,这是行不通的。首先,你的意思是“回归t”而不是“等待”;? (没有做任何事情后会“等待”什么,对不对?)如果是这样,我们不会回到我们开始的地方吗?还是我错过了一些东西(再次!)? –
@LarrySmith如果你遗漏了尾部,等待'ProcessSingleUrlInner'返回的任务将会在* ProcessWebPage完成之前完成。等待它“包含”ProcessWebPage到函数中。它确保'ProcessSingleUrlInner'在'ProcessWebPage'完成之前没有完成。这就是这个解决方案的关键:你得到的任务只有在* everything *完成时才能完成。那是你想要的,对吧? – usr