采集器使用的是System.Windows.Forms.WebBrowser, 在constructor里面添加了DocumentChanged的event handler, 来模拟浏览器访问webmaster的流程, 访问external-links页面时便修改constructor传进来的LinkProfile
在主线程里是new WebmasterScarper(website, link_profile)之后接着就new LinkProfileTemplate(link_profile)
本来以为采集器应该走完流程才创建LinkProfileTemplate, 但是发现创建的LinkProfileTemplate是空图表, Debug时又发现new LinkProfileTemplate() 比 WebBrowser.DocumentChanged的event handler更早执行, 现在才想起来event handler可能是单独一个线程?
接着在new LinkProfileTemplate()之间加了循环检测: 如果link_profile为空就使进程sleep 1秒, 然后继续检测, Debug发现这个循环一直没有停止, 而且DocumentChanged的event handler一直没有被调用
这时候想 他们可能是在同一个线程?
接着给采集器单独建了一个线程执行, browser.Navigate()处出现了异常{"Unable to get the window handle for the 'WebBrowser' control. Windowless ActiveX controls are not supported."}, InnerException是{"Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on."}
确实创建的线程和存取的线程不是同一个线程:
WebmasterScraper scraper = new WebmasterScraper(website, link_profile);
new Thread(scraper.start).Start();
这么说WinForm的控件不是thread safe
按照这个方法来使用Control.Invoke():
http://www.perceler.com/articles1.php?art=crossthreads1
还是会出现同样的错误
然后把constructor的方法移到了start()中(bad smell..), 出现了另一个异常System.Threading.ThreadStateException: Could not instantiate ActiveX control 'GUID' because the current thread is not in a single-threaded apartment.
最后没办法只有把主线程的之后的代码都放到scraper中了..(powerless..)