我有一个应用程序,它从web上获取大量信息,并将其显示在WPF的窗口中。当然,信息获取是在多个后台线程中完成的;它们中的大多数不应该是计算密集型的(除了一些文本解析),但主要依赖于获取but内容(webclient.Download。和类似)。
因为我必须发送很多请求,所以我启动了很多线程,否则用户将不得不等待几个小时才能完成所有加载;因为这些线程中的许多主要是等待来自网络的数据和/或启动对new服务的新请求,理论上这应该不是问题。然而,在实践中,调度程序的性能通常比没有线程运行时要差得多。
后台线程是通过混合使用TPL数据流管道和Parallel.ForEach方法创建的。我也已经尝试通过指定MaxThreads来限制线程的数量,但是由于任何数据流块都可以启动Parallel.Foreach块,所以我认为这样做效果不是很好。
有没有其他方法可以提高调度程序的优先级、性能或减少卡顿?
编辑:任务/线程的数量通常在50-100之间,在最坏的情况下可能会更多一点。weblookup的一个典型场景是:向webservice发送请求,解析响应(<10kb字符串)。对于每个响应,(parallel.foreach)下载此响应的数据,下载/缓存响应中的任何图像并解析响应(例如,删除维基百科文章中的任何链接);等待它们全部完成并移动到下一个查找。
发布于 2014-07-18 20:34:40
与其启动一个新线程来下载数据,不如考虑使用异步版本的下载函数,比如WebClient.DownloadDataTaskAsync。这样你就不需要启动线程了。只需调用
var result = await webClient.DownloadDataTaskAsync并在await之后对结果进行处理。这将基本上启动下载操作并返回。下载完成后,将执行该方法的其余部分。最棒的是,它不使用任何额外的线程。
发布于 2014-07-18 20:38:37
由于没有代码示例,根据您的帖子的语气,在我看来,通过使用基于异步IO的模式,您可以完全节省使用TPL Datablock或Parallel.ForEach提供的线程的使用。
如果你的主要目标是下载网页内容,我会尝试基于Task Asynchronous Pattern的方法。例如,这是使用HttpClient
public async Task<string> DownloadWebContentAsync(string url)
{
var client = new HttpClient();
// Assuming a GET request
var response = await client.GetAsStringAsync(url);
// Do some string processing..
return response;
}现在,使用它:
await DownloadWebContentAsync(url);发布于 2014-07-18 20:24:01
我不清楚你的后台线程是否像你说的那样不会引起太多的CPU负载。即使在平均情况下,它们造成的负载很小,负载也可能会激增并导致卡顿。
尝试将后台工作放在优先级较低的TaskScheduler上。Parallel Extension Extras有一个支持它的TaskScheduler。
您多久更新一次UI?也许它太频繁了。限制更新频率。
我们到底讨论了多少个线程?如果这一数字达到数百,请考虑使用异步IO。异步IO操作在运行时不使用线程。甚至连后台线程都没有。
https://stackoverflow.com/questions/24824857
复制相似问题