【发布时间】:2021-01-06 18:40:55
【问题描述】:
我遇到了一个我似乎无法弄清楚的任务问题。此应用程序通过 WebClient 对多个服务器进行重复的 HTTP 调用。它维护一个运行 HTTP 调用的任务字典,每五秒钟检查一次结果,然后一旦结果出现,它就会再次进行 HTTP 调用。这将在应用程序的整个生命周期内持续进行。
最近,它开始出现任务随机卡在 WaitingForActivation 中的问题。在调试器中,任务显示为“[计划并等待运行]”,但它从未运行。
这是它正在运行的函数,当我在调试器中单击“Scheduled”任务时,它指向 DownloadStringTaskAsync() 行:
private static async Task<string> DownloadString(string url)
{
using (var client = new WebClient()) {
try {
var result = await client.DownloadStringTaskAsync(url).ConfigureAwait(false);
return result;
} catch (WebException) {
return null;
}
}
}
实际创建运行上述函数的任务的代码是这样的。它仅在现有任务完成后才到达此行,Task.IsCompleted 永远不会返回 true,因为它处于计划状态。 Task.Status 卡在 WaitingForActivation 中。
tasks[resource] = Task.Run(() => DownloadString("http://" + resources[resource] + ":8181/busy"));
关于这件事的奇怪之处在于,据我所知,这段代码在两年内运行得非常好,直到我们最近进行了一次服务器迁移,其中包括升级的操作系统并引发了网络丢包问题。那是我们开始注意到这个特殊问题的时候,虽然我不知道这两者之间有什么关系。
此外,这往往仅在应用程序运行数千秒后才会发生。它在一段时间内运行得非常好,直到一个接一个的任务开始卡住。大约一天后,通常会有四五个任务卡在计划中。由于第一个任务卡住通常需要一些时间,所以在我看来会有某种竞争条件,但我不明白这是怎么回事。
任务会卡在计划中并且从未真正运行过吗?
【问题讨论】:
-
WaitingForActivation不是“已计划并等待运行” - 您确定您正在查看相同的任务吗?WaitingForActivation中的任务一段时间是完全正常的,无需担心。WaitingToRun一段时间内的任务,通常表示线程池饱和。 -
你想达到什么目的?了解为什么某些线程没有在您不需要线程的代码中启动,或者使软件工作?删除包装
Task.Run并再次检查。要回答最初的问题,需要更多信息,例如有多少任务同时工作。稍后会发生什么,在 Task 完成后(您是否将其从字典中删除?并发字典?),正在使用什么样的 TaskSceduler,环境是什么等。换句话说,只有可重现的示例才能帮助我找出最初的内容发生。顺便说一句,您对我的回答有任何反馈吗? -
还有一件事:
WebClient为每个请求创建新的 TCP 连接,这样你可能会用完套接字。然后答案中的HttpClient可能会有所帮助,因为它可以重用打开的连接。试一试。 -
至于我在寻找什么,我想了解为什么任务没有开始,所以我可以从中获得一些额外的知识,但我可以满足于获得应用程序好好工作。代码中有很多任务正在进行,大约有十几个显示在任何给定时刻计划/运行(其中大约一半与此代码相关)。任务完成后,在接下来的 5 秒循环中,它将开始一个新的循环 - 相同的
task[resource]行将运行用新的任务替换已完成的任务。这是一个非并发字典。 -
我没有使用任何任务调度程序 - 我只有很多 Task.Run() 和 async/await 乱七八糟。 (很确定其中很多是不必要的。)环境是 Windows 2016 服务器,项目针对框架 4.6.1,应用程序通常作为 Windows 服务运行,虽然我一直在调试它,但我一直在通过 Visual 运行它工作室。
标签: c# .net async-await