WatiN 挂在“about:blank”上对于多个并发 IE8 实例
我正在尝试使用最新版本的 WatiN 测试多个网站。
如果尝试同时运行多个测试,WatiN 最终将抛出异常“Internet Explorer 繁忙时超时”。发生这种情况是因为 Internet Explorer 最终在尝试连接“about:blank”时“卡住”。
运行时环境:
- Windows 7 Professional
- Internet Explorer 8(版本8.0.7600.16385)
- WatiN(版本2.1.0.1196)
我已将问题提炼为以下简单的c#控制台程序。要重现该问题,请从 Visual Studio 创建一个新的 c# .NET 3.5 控制台程序,添加对 WatiN.Core.dll 的引用,编译,然后运行。在我的机器上大约 10 秒后,IE 挂在“about:blank”上,最终 WatiN 超时并生成异常。
增加 WatiN 超时只会延迟问题的发生。
还有其他人看到这个问题吗?您能使用我的示例程序重现该问题吗?有什么解决办法吗?
[代码]
namespace IEBugUsingWatiN
{
using System;
using System.Collections.Generic;
using System.Threading;
using WatiN.Core;
class Program
{
const int MAX_THREADS = 7;
volatile static bool _stopAll = false;
static void Main( string[] args )
{
Console.WriteLine( "Initializing WatiN." );
var watinSettings = WatiN.Core.Settings.Instance;
watinSettings.AutoCloseDialogs = false;
watinSettings.AutoMoveMousePointerToTopLeft = false;
watinSettings.AutoStartDialogWatcher = false;
watinSettings.HighLightElement = false;
watinSettings.SleepTime = 200;
watinSettings.WaitUntilExistsTimeOut = 15;
Console.WriteLine( "Creating threads." );
List<Thread> threads = new List<Thread>();
for ( int numThreads = 0 ; numThreads < MAX_THREADS ; ++numThreads )
{
var thread = new Thread( ThreadFunc );
thread.IsBackground = true;
thread.SetApartmentState( ApartmentState.STA );
thread.Start();
threads.Add( thread );
}
Console.WriteLine( "Press Enter key to end tests..." );
Console.ReadLine();
_stopAll = true;
Console.WriteLine( "Waiting for all threads to end..." );
foreach ( var thread in threads )
{
thread.Join();
}
Console.WriteLine( "Done." );
}
static void ThreadFunc()
{
while ( !_stopAll )
{
WatiN.Core.IE ie = null;
try
{
ie = new WatiN.Core.IE();
ie.GoTo( "http://www.hertz.com" );
}
catch ( System.Exception ex )
{
_stopAll = true;
Console.WriteLine( "EXCEPTION: {0}", ex.Message );
}
if ( null != ie )
{
ie.Close();
ie = null;
}
Thread.Sleep( TimeSpan.FromSeconds( 1 ) );
}
}
}
}
[更新]
Microsoft 已确认这是一个已知错误。长话短说,IE(特别是wininet.dll)在某些情况下会泄漏连接。唯一建议的解决方法是在运行测试后显式终止所有 Internet Explorer 进程实例。 “修复”不太可能,因为这已经是多年来的问题,而且他们担心会破坏与现有应用程序的兼容性。
仅供参考,这是微软不得不说的:
最好的解决方法可能是 每隔一定时间终止并重新启动 IE 在测试运行自动化期间。你 可以定期重启 IE 间隔或有某种 代码中的检测逻辑。什么时候 你会遇到这种情况 IE 不会 能够提出任何要求,所以我 期望应用程序 接收 BeforeNavigate 事件(如果 你沉没了这个事件)设置一个计时器 当计时器触发检查时 看看你是否曾经得到过 URL 的 DocumentComplete 事件(您可能不会)。这是一个 很好的迹象表明您遇到了 问题所以你可以继续杀死和 此时重新启动 IE 进程。
...这种方法并没有解决 wininet 连接丢失的根本原因 但同时没有任何 您可以掌控的实用方法 来做到这一点。只是为了提供一些 关于你如何进入这个领域的观点 情况...
只要有 ActiveX 组件 (例如msxml发出AJAX请求) 发出 HTTP 请求和 Tab 托管该组件的窗口是 在响应之前关闭 收到后,IE 有机会 失去 wininet 连接,如果 ActiveX 不会中止调用。这 这正是赫兹发生的事情 设想。该页面有脚本正在运行 发出 AJAX 请求。 IE窗口 然后在响应之前关闭 回来了。部分拆除后 该页面,IE调用ActiveX (在本例中为 MSXML)通知 关闭时的控制。这 然后控件可以中止该连接 被摧毁后。 MSXML 没有 中止此处的连接导致 泄漏。这个问题根深蒂固 IE的设计架构以及它是如何 与第 3 方组件交互。 因此,您很可能会 在以下网站上遇到此问题 有 AJAX 请求。历年 有多个针对的错误 这个问题,但所有这些错误都是 因申请过高而被拒绝 兼容性风险。部分难度 提供修复的是 IE 不 始终知道 ActiveX 是 一个建立连接。
Wininet 不公开任何机制 用于重置第三方控件或 清理 wininet 连接丢失。 默认情况下 IE6/7 每个有 2 个连接 服务器,而 IE8 有 6 个,所以这个 行为可能不太明显 IE8。有一个注册表项 记录在这里 http://support.microsoft.com/kb/183110 你可以尝试增加数量 可用的连接。然而这 只会拖延问题的解决。这是 为什么我提到唯一可支持的 重置 wininet 状态的方法是 重新启动 IE 进程。
I’m trying to test several web sites using the latest version of WatiN.
If a try to run several tests simultaneously, WatiN will eventually throw an exception “Timeout while Internet Explorer busy”. This occurs because Internet Explorer eventually gets “stuck” trying to connect to “about:blank”.
Runtime environment:
- Windows 7 Professional
- Internet Explorer 8 (Version 8.0.7600.16385)
- WatiN (Version 2.1.0.1196)
I have distilled the problem to the following bare-bones c# console program. To recreate the problem, create a new c# .NET 3.5 console program from Visual Studio, add a reference to WatiN.Core.dll, compile, then run. After about 10 seconds on my machine, IE hangs on "about:blank", and eventually WatiN times out and generates an exception.
Increasing the WatiN timeouts only delays the problem.
Has anyone else seen this problem? Can you reproduce the problem using my example program? Any solutions?
[Code]
namespace IEBugUsingWatiN
{
using System;
using System.Collections.Generic;
using System.Threading;
using WatiN.Core;
class Program
{
const int MAX_THREADS = 7;
volatile static bool _stopAll = false;
static void Main( string[] args )
{
Console.WriteLine( "Initializing WatiN." );
var watinSettings = WatiN.Core.Settings.Instance;
watinSettings.AutoCloseDialogs = false;
watinSettings.AutoMoveMousePointerToTopLeft = false;
watinSettings.AutoStartDialogWatcher = false;
watinSettings.HighLightElement = false;
watinSettings.SleepTime = 200;
watinSettings.WaitUntilExistsTimeOut = 15;
Console.WriteLine( "Creating threads." );
List<Thread> threads = new List<Thread>();
for ( int numThreads = 0 ; numThreads < MAX_THREADS ; ++numThreads )
{
var thread = new Thread( ThreadFunc );
thread.IsBackground = true;
thread.SetApartmentState( ApartmentState.STA );
thread.Start();
threads.Add( thread );
}
Console.WriteLine( "Press Enter key to end tests..." );
Console.ReadLine();
_stopAll = true;
Console.WriteLine( "Waiting for all threads to end..." );
foreach ( var thread in threads )
{
thread.Join();
}
Console.WriteLine( "Done." );
}
static void ThreadFunc()
{
while ( !_stopAll )
{
WatiN.Core.IE ie = null;
try
{
ie = new WatiN.Core.IE();
ie.GoTo( "http://www.hertz.com" );
}
catch ( System.Exception ex )
{
_stopAll = true;
Console.WriteLine( "EXCEPTION: {0}", ex.Message );
}
if ( null != ie )
{
ie.Close();
ie = null;
}
Thread.Sleep( TimeSpan.FromSeconds( 1 ) );
}
}
}
}
[Update]
Microsoft has confirmed that this is a known bug. To make a long story short, IE (specifically, wininet.dll) leaks connections under certain circumstances. The only suggested workaround is to explicitly kill all Internet Explorer process instances after running a Test. A "fix" is not likely since this has been an issue for YEARS, and they are afraid of breaking compatibility with existing applications.
FYI, here is what Microsoft has to say:
The best workaround would probably to
kill and restart IE at some interval
during your test run automation. You
can restart IE at some regular
interval or have some kind of
detection logic in your code. When
you get into this situation IE won’t
be able to make any request out so I
would expect the application to
receive a BeforeNavigate event (if
you sink this event) set up a timer
and by the time the timer fires check
to see if you ever get a
DocumentComplete event for the URL (which you probably won’t). This is a
good indication that you run into the
problem so you can proceed to kill and
restart the IE process at this point....this approach is not addressing the
root cause of wininet connection loss
but at the same time there aren’t any
practical approach within your control
to do this. Just to provide some
perspective on how you get into this
situation…Whenever there are ActiveX components
(such as msxml making an AJAX request)
making an HTTP request and the Tab
window hosting that component is
closed before the response is
received, there is a chance IE will
lose that wininet connection if the
ActiveX does not abort the call. This
is exactly what happened in the hertz
scenario. The page has script running
to issue an AJAX request. IE window
is then closed before the response
comes back. Upon part of tearing down
the page, IE calls into the ActiveX
(MSXML in this case) to notify the
control upon shutting down. The
control can then abort that connection
upon being destroyed. MSXML does not
abort the connection here leading to
the leak. The issue is deeply rooted
in IE’s design architecture and how it
interacts with 3rd party components.
Because of this you will most likely
encounter this issue on web sites that
have AJAX requests. Over the years
there are multiple bugs opened against
this issue but all those bugs were
rejected due to high application
compat risk. Part of the difficulty
in providing a fix is that IE does not
always know that the ActiveX is the
one making a connection.Wininet does not expose any mechanism
for a 3rd party control to reset or
clean up the wininet connection loss.
By default IE6/7 has 2 connections per
server while IE8 has 6 so this
behavior is probably less visible in
IE8. There is a registry key
documented here
http://support.microsoft.com/kb/183110
you can try to increase the number of
available connections. However this
is only delaying the problem. This is
why I mentioned the only supportable
way to reset the wininet state is to
restart the IE process.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论