我看到正在运行使用硒webdriver的,简单的例子是,比如并行嵌套循环网络压力测试的一些死亡实例的怪事,创下每100次展示300个独特的网页。
我“成功”获得4 - 8 webdriver的情况下使用会ThreadLocal<FirefoxWebDriver>
对他们每个任务线程隔离和MaxDegreeOfParallelism在ParallelOptions实例来限制线程。 我的分区和并行外环只(页面的集合),并检查.IsValueCreated
上ThreadLocal<>
每个分区的“长期运行的任务”的方法开始内部容器。 为了便于以后清理,我每一个新的实例添加到由线程ID键控ConcurrentDictionary。
不管我用什么并列化或分区策略,webdriver的情况下,偶尔会做下列之一:
- 启动,但永远不会显示一个URL或运行印象
- 启动,运行任意数量的印象很好,然后就闲置在某些点
当其中任一发生,并行循环,最终似乎注意到一个线程没有做任何事情,并产生一个新的分区。 如果n是允许的线程的数目,这导致在具有n个生产线仅约50-60%的时间。
清理仍然工作在最后罚款; 也可以是2N打开的浏览器或以上,但生产性和非生产性的人都得到清理。
有没有一种方法来监视这些无用的webdriver实例和)清除它们向右走,加上B)得到的并行循环立即更换,而不是落后了好几分钟,因为它现在经常做的任务段,?
由于没有OnReady
事件也不是IsReady
财产,我的工作围绕它通过创建每个实例后睡觉线程几秒钟。 这样做似乎给我100%坚固耐用,功能的webdriver实例。
感谢您的建议 ,我已经实现IsReady
在我的开源项目功能Webinator 。 使用,如果你想,或者使用下面列出的代码。
我试图实例25分的情况下,和所有的人是有功能的,所以我在这一点上我的算法非常有信心,(我的杠杆作用HtmlAgilityPack,看是否存在的元素,但在这里我要跳过它为简单起见):
public void WaitForReady(IWebDriver driver)
{
var js = @"{ var temp=document.createElement('div'); temp.id='browserReady';" +
@"b=document.getElementsByTagName('body')[0]; b.appendChild(temp); }";
((IJavaScriptExecutor)driver).ExecuteScript(js);
WaitForSuccess(() =>
{
IWebElement element = null;
try
{
element = driver.FindElement(By.Id("browserReady"));
}
catch
{
// element not found
}
return element != null;
},
timeoutInMilliseconds: 10000);
js = @"{var temp=document.getElementById('browserReady');" +
@" temp.parentNode.removeChild(temp);}";
((IJavaScriptExecutor)driver).ExecuteScript(js);
}
private bool WaitForSuccess(Func<bool> action, int timeoutInMilliseconds)
{
if (action == null) return false;
bool success;
const int PollRate = 250;
var maxTries = timeoutInMilliseconds / PollRate;
int tries = 0;
do
{
success = action();
tries++;
if (!success && tries <= maxTries)
{
Thread.Sleep(PollRate);
}
}
while (!success && tries < maxTries);
return success;
}
假设是,如果浏览器响应的JavaScript函数,并寻找元素,那么它可能是一个可靠的实例,并随时可以使用。
我有一个类似的问题。 事实证明,webdriver的没有寻找开放端口的最好方法。 如上所述这里沾到端口的系统范围的锁,找到开放的端口,然后启动实例。 这可以饿死,你试图启动端口的其他实例。
我解决此得到了通过直接在代表用于指定随机端口号ThreadLocal<IWebDriver>
是这样的:
var ports = new List<int>();
var rand = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
var driver = new ThreadLocal<IWebDriver>(() =>
{
var profile = new FirefoxProfile();
var port = rand.Next(50) + 7050;
while(ports.Contains(port) && ports.Count != 50) port = rand.Next(50) + 7050;
profile.Port = port;
ports.Add(port);
return new FirefoxDriver(profile);
});
这个工程相当一致的我,但如果你最终是没有解决使用列表中所有50个有问题。