如何下载更快?

时间:2011-11-06 17:49:43

标签: delphi indy synapse

将网页源下载到备忘录组件的最快方法是什么?我使用Indy和HttpCli组件。

问题是我有一个填充了100多个站点的列表框,我的程序将源代码下载到备忘录并解析该源文件的mp3文件。它类似于谷歌音乐搜索程序;它使用Google查询来简化Google搜索。

我开始阅读导致我的问题的线程:我可以在具有解析功能的线程中创建一个IdHttp实例并告诉它解析列表框中一半的网站吗?

所以基本上当用户点击解析时,主线程应该这样做:

for i := 0 to listbox1.items.count div 2 do
    get and parse

,另一个线程应该这样做:

for i := form1.listbox1.items.count div 2 to form1.listbox1.items.count - 1 do
    get and parse.

,因此他们会在同一时间将已解析的内容添加到form1.listbox2。或者在主线程中启动两个IdHttp实例可能更容易;一个是上半部分,另一个是第二个?

为此:我应该使用Indy还是Synapse?

2 个答案:

答案 0 :(得分:9)

我会创建一个可以读取单个URL并处理其内容的线程。然后,您可以决定要同时触发的线程数量。您的计算机将允许相当多的连接,因此如果这100个站点具有不同的主机名,则同时运行10或20不是问题。太多是过度杀伤,但是太少会浪费处理器时间。

您可以通过单独的线程进行下载和处理来进一步调整此过程,以便您可以让许多线程不断下载内容。下载不是处理器密集型的。它基本上等待响应,因此您可以轻松拥有相对大量的下载线程,而其他几个工作线程可以从结果池中获取项目并处理它们。
但拆分下载和处理会让它变得有点复杂,我认为你还没有接受这个挑战。

因为目前,你还有其他一些问题。首先,在线程中不使用VCL组件。如果您需要线程中列表框中的信息,则需要在线程中使用Synchronize来对主线程进行“安全”调用,否则您必须在启动线程之前传递所需的信息。后者更有效,因为使用Synchronize执行的代码实际上在主线程中运行,使您的多线程效率降低。

但实际上我的注意力被吸引到第一行,“将网页源下载到备忘录组件”。不要那样做!请勿将这些结果加载到备忘录中进行处理。自动处理最好在内存中,在可视控件之外完成。使用字符串,流甚至字符串列表来处理文本比使用备忘录更快。
字符串列表也有一些开销,但它使用相同的索引结构(TMemoStrings,它是Memo的Lines属性,而TStringList都具有相同的祖先),所以如果你有代码使得使用它,将它转换为TStringList非常容易。

答案 1 :(得分:5)

我建议在线程中进行所有解析,不要让主线程进行任何解析。主线程应该只管理UI。不要从TMemo解析HTML,让每个线程下载到TStream或String,然后直接解析。使用TIdSync或TIdNotify将解析结果发送到UI进行显示(如果速度很重要,请使用TIdNotify)。在解析逻辑中使用UI组件会降低它的速度。