更新,web多线程分析下载网页的阻塞问题,如何让线程等待下载完毕,执行web回调函数,同时不阻塞其他线程?

[ 648 查看 / 3 回复 ]

之前写的100个网址的例子有点问题,重新写了一下循环,代码已经更新了
请教一下关于web多线程分析下载网页的问题,假设有100个网址,1.com,2.com,3.com,.........100.com,我想开2线程,一个线程依次下载奇数的网址,另一个下载偶数的网址,也就是1,3,5。。。和2,4,6。。。的网址,下面是大体框架:
  1. web.loadProc = function(url,wb) --下载完成回调函数,url当前网址,wb当前窗体对象,这里教程错了,第二个参数不是hwnd,应该是wb对象
  2.     --通过参数url,分析得到线程是第一个还是第二个,第一个线程的url都是奇数,第二个线程的url都是偶数,这里就写作x,x=1或者x=2
  3.     isThreadOk[x]=true ----线程已经完成
  4. end;
  5. ----------------------------------------
  6. win.consoleOpen()
  7. threadTab={} ---------存储线程的 tab
  8. isThreadOk={} --------存储线程状态的 tab

  9. threadTab[1]=web.new()
  10. threadTab[1]:setTitle(true)
  11. threadTab[1]:setScroll(true)
  12. threadTab[1]:setSilent(true,true,true,true)
  13. threadTab[1]:setDL(DLCTLNORUNACTIVEXCTLS | DLCTLNODLACTIVEXCTLS)
  14. isThreadOk[1]=true -------线程1 是否可用

  15. threadTab[2]=web.new()
  16. threadTab[2]:setTitle(true)
  17. threadTab[2]:setScroll(true)
  18. threadTab[2]:setSilent(true,true,true,true)
  19. threadTab[2]:setDL(DLCTLNORUNACTIVEXCTLS | DLCTLNODLACTIVEXCTLS)
  20. isThreadOk[2]=true -------线程2 是否可用

  21. --------------------------------------- 分配线程完毕

  22. mThreadCount=math.floor(100/2) -------每个线程访问的次数,一共 2 个线程,应该是50次
  23. for i=0,mThreadCount,1 do
  24.     for k,v in pairs(threadTab) do
  25.         mUrl="http://"..tostring((2*i+tonumber(k)))..".com"  ----当前准备访问的网址
  26.         if (2*i+tonumber(k))<=100 and isThreadOk[k]=true) then --如果没到最后一个网址,而且线程已经完成,就可以继续下一个网址
  27.             isThreadOk[k]=false ----访问之前,先设置为线程未完成
  28.             threadTab[k]:go(mUrl)
  29.         else
  30.             --如果这个线程没完成的话,就应该等待他,直到完成或超时,然后进行下一个网址。问题就在这里,设置delay(1000)或者threadTab[1]:wait()的话,就阻塞了下面偶数线程,整个程序变为单线程了,不设置的话,这个线程就不停地go(mUrl),很快的中间没有间隙,web.loadProc根本没有机会触发。我想请教一下,这里如何设置,才可以让线程1和线程2,互相不影响,可以线程1访问网址,分析网址,取得分析的结果,再进行下一个奇数网址?
  31.         end;
  32.     end;
  33. end;
复制代码
----就是这样的问题,想了两天,试验了没有结果,要么就是单线程一样,要么就是一下子全部访问,而没有执行web.loadProc,很伤脑筋,我自己是在判断线程未完成那里,设了一个 while循环和delay,等待2.5秒,若果还没有完成,那么就访问下一个网址,看console截图,有点多线程的感觉,十几个线程一下子开启,可是看网络状态截图,带宽似乎还没怎么占用,应该还可以更快的下载,求高手解答,判断部分代码和运行的截图如下:
_threadNum是用户输入的线程个数,_maxPage是总页数,具体细节大体就是上面2线程的延伸,每个线程访问特定的页数,运行起来,就像等差数列一样,一共n个线程,线程1访问1,1+n,1+n+n页,线程2访问2,2+n,2+n+n页。。。

  1. mThreadCount=math.floor(_maxPage/_threadNum) -------每个线程访问的次数,一共_threadNum 个线程

  2. for i=0,mThreadCount,1    do
  3.     for k,v in pairs(_threadTab) do
  4.         mUrl=url1.._sId..url2..tostring((_threadNum*i+tonumber(k)))..url3.._maxPage..url4
  5.         if (_threadNum*i+tonumber(k) <= _maxPage and _isThreadOk[k] and nStop()) then --检测是空闲线程?
  6.             print("线程 "..k.." 开始访问第:",tostring((_threadNum*i+tonumber(k))).." 页。。。")
  7.             _isThreadOk[k]=false
  8.             v:go(mUrl)
  9.             -- ele=v:waitEle("Foot",2000) --这句我没执行,我在原函数基础上添加了一个超时的参数
  10.         elseif (_threadNum*i+tonumber(k) <= _maxPage and _isThreadOk[k]==false and nStop()) then --如果不是空闲线程
  11.             mTime1=os.tick()
  12.             while( (_isThreadOk[k]==false) and (os.tick()-mTime1<=2500) and nStop() ) do --------------等待他变成空闲状态,超时 2.5 秒,阻塞了其余线程,这个时间内有些线程已经完成,但是也要等待,2.5秒后,大部分线程应该下载完毕了
  13.                 -- print("等待线程:"..k.." 变成空闲状态 0.1秒")
  14.                 delay(50)
  15.             end;
  16.             if (_isThreadOk[k]==false) then
  17.                 print("\r\n!!!!!!!!!!不等了,线程 "..k.." 开始访问第:",tostring((_threadNum*i+tonumber(k))).." 页。。。\r\n")
  18.             end;
  19.             v:go(mUrl)
  20.             -- ele=v:waitEle("Foot",2000)--这句我没执行
  21.         else
  22.             break;
  23.         end;
  24.     end;
  25. end;
复制代码
排版还真是体力活!:~
最后编辑iroieguy 最后编辑于 2009-06-28 20:07:21
xiancheng1.jpg ()

模拟精灵截图1 (2009-6-26 23:29:31)

EXIF信息

xiancheng1.jpg

xiancheng2.jpg ()

模拟精灵截图2 (2009-6-26 23:29:31)

EXIF信息

xiancheng2.jpg

分享 转发
TOP

留名

回来研究下。。。。
TOP

等下贴一个具体的代码例子,以便大家研究
TOP

就是下面的代码,功能是3个线程循环访问google baidu 和 yahoo,运行速度不快,感觉线程循环出了问题,但又不知道该怎么写好
  1. <?xml version="1.0" encoding="gb2312" ?>
  2. <!--关闭"信息窗口"可以提升效率加快速度
  3. 创建时间:2009年06月28日-15:27-->
  4. <脚本区块 语言="LAScript" 名称="init" 延时="0" 启用="true" 编辑密钥="" 运行公钥="">
  5. <![CDATA[ 
  6. --区块名字前添加"init"前缀则不会重复运行
  7. _set = ape:loadSetting(); --读取自定义属性
  8. stopPlay = function() --这个函数回放停止时被调用.
  9. ape:saveSetting(_set); --保存自定义属性
  10. collectgarbage();--清理内存
  11. end;
  12. --请在下面添加不需要重复运行的脚本
  13. --[[ 添加横线取消注释块
  14. do return false end; --退出程序
  15. do return "区块名字" end;--转向指定区块
  16. do return 2 end;--转向第二个区块
  17. --]]
  18. import("std"); --从外部文件引用名字空间
  19. ----------------------------------------
  20. web.loadProc = function(url,wb) --下载完成回调函数,url当前网址,wb当前窗体对象,这里教程错了,第二个参数不是hwnd,应该是wb对象
  21.     if (string.find( url,"google",1,true)) then
  22.         isThreadOk[1]=true
  23.         print(" 线程 1 已经完成!\r\n")
  24.     elseif (string.find( url,"baidu",1,true)) then
  25.         isThreadOk[2]=true
  26.         print(" 线程 2 已经完成!\r\n")
  27.     elseif(string.find( url,"yahoo",1,true)) then
  28.         isThreadOk[3]=true
  29.         print(" 线程 3 已经完成!\r\n")
  30.     end;
  31. end;
  32. ----------------------------------------
  33. win.consoleOpen()
  34. threadTab={} ---------存储线程的 tab
  35. isThreadOk={} --------存储线程状态的 tab
  36. mUrl={}
  37. mUrl[1]="http://www.google.com"
  38. mUrl[2]="http://www.baidu.com"
  39. mUrl[3]="http://www.yahoo.cn"
  40. x=0
  41. for i=1,3,1 do
  42.     threadTab[i]=web.new()
  43.     threadTab[i]:setSilent(true,true,true,true)
  44.     threadTab[i]:setDL(_DLCTL_NO_RUNACTIVEXCTLS | _DLCTL_NO_DLACTIVEXCTLS)
  45.     isThreadOk[i]=true -------线程 i 是否可用
  46. end;
  47. --------------------------------------- 分配线程完毕
  48. print("\r\n******************第 "..(x+1).." 轮,访问 "..(3*x+1).." -> "..(3*x+3).." 个\r\n")
  49. while( (true) and nStop() ) do
  50.     for i=1,3,1 do
  51.         if (isThreadOk[i]==true and nStop()) then --如果线程已经完成,就可以继续下一个网址
  52.             print(" 线程 "..i.." 开始访问第 "..(3*x+i).." 个")
  53.             isThreadOk[i]=false ----访问之前,先设置为线程没完成
  54.             threadTab[i]:go(mUrl[i])
  55.         elseif (isThreadOk[i]==false and nStop()) then
  56.             print(" 线程 "..i.." 还没完成,等下吧。这个线程等待的同时,其他线程有的已经完成,应该提前进入下一轮,但是被阻塞了\r\n")
  57.             threadTab[i]:wait() --------------大家可以把这句注释掉,看看什么情况
  58.             if (isThreadOk[i]) then
  59.                 print(" 线程 "..i.." 回到工作,开始访问第 "..(3*x+i).." 个")
  60.             else
  61.                 print(" 不等了,线程 "..i.." 强行回到工作,开始访问第 "..(3*x+i).." 个")
  62.             end;
  63.             threadTab[i]:go(mUrl[i])
  64.         elseif (not nStop()) then
  65.             break;
  66.         end;
  67.     end;
  68.     x=x+1
  69.     print("\r\n******************第 "..(x+1).." 轮,访问 "..(3*x+1).." -> "..(3*x+3).." 个\r\n")
  70. end;

  71. ]]>
  72. </脚本区块>
  73. <脚本区块 语言="LAScript" 名称="LAScript" 延时="0" 启用="true" 编辑密钥="" 运行公钥="">
  74. <![CDATA[
  75. --请在下面添加脚本代码(重复运行)
  76. ]]>
  77. </脚本区块>
  78. <数据区块 />
复制代码
最后编辑iroieguy 最后编辑于 2009-06-28 20:51:07
TOP