This is post #34 in the Building Neno series. Please click here for a description of the Building Neno project and instructions on how to access the source code for this post.
This post is mostly for my own future reference in case I ever revisit this. I've been tinkering with the screenshot generator to increase it's performance. Despite having the disk and database work farmed out to worker threads, the WebBrowser
controls still take a long time to browse their respective pages. I suspect they're not all working at the same time.
I initially thought my low performance might be because all my WebBrowser
controls are on the same thread, or it might be some kind of bottleneck on the underlying ActiveX control itself. So I rolled a new screenshot generator, a console application this time, that spawns a new STA thread for each WebBrowser
control like this...
for (int x = 1; x < 9; x++)
{
var thread = new Thread(
number =>
{
var webBrowser = new WebBrowser { Height = 1024, Name = "WebBrowser" + (int)number, ScrollBarsEnabled = false, Width = 1024 };
webBrowser.DocumentCompleted += WebBrowser_DocumentCompleted;
if (NavigateToNextPost(webBrowser))
Application.Run();
});
thread.SetApartmentState(ApartmentState.STA);
WebBrowserThreads.Add(thread);
thread.Start(x);
Console.WriteLine("WebBrowser{0} spawned.", x);
}
foreach (Thread thread in WebBrowserThreads)
thread.Join();
Windows Forms controls require an STA thread and a message pump, which is what the call to Application.Run
is all about. The boolean check is there to make sure there is a post for the control to navigate to, otherwise the thread simply exits.
The call to Application.Run
is accompanied by a call to Application.ExitThread
to stop the message pump when the thread is done.
private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var webBrowser = (WebBrowser)sender;
CaptureScreenshot(webBrowser, e.Url.ToString());
if (!NavigateToNextPost(webBrowser))
Application.ExitThread();
}
It all runs great, with the disk and database work still handled by additional threads. But the overall improvement is only 9.5 seconds.
The WebBrowser
controls seem to run slowly, one after the other, like they're sharing a common resource. This could be my imagination -- I simply don't know and I'm not sure how to find out. I've spent more time than I want to on this, so I'll just keep it in mind and move on. The application runs, it just doesn't run as fast as I had hoped.
One thing I did notice when playing around with the screenshot generator is that the screenshots weren't rendering exactly right. There was some extra padding in places, and floats were behaving differently. Checking the same pages in IE8 showed everything to be okay... So why was the WebBrowser
control rendering differently from IE8?
The answer lies in how the WebBrowser
control renders by default, which is explained here. To avoid breaking existing applications that use the WebBrowser
control, the control renders in IE7 standards mode by default. To make it run in IE8 standards mode, a registry key must be added to the computer the application is running on. It can't be set via .NET... I was somewhat incredulous when I read this, but I suppose it isn't a .NET control, just a managed wrapper, and as such will have some of its native implementation poking through here and there.
Setting "ssg2.exe" = 8000
under HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION
didn't work for me. I had to set it to 8888 instead. "ssg.vshost.exe"
didn't help in the 8000 scenario and wasn't required to get 8888 to work. The end result was a much nicer render in my screenshots, albeit with a bad taste in my mouth from modifying the registry.
I could get my site to render 100% correctly in IE7, but that's not my idea of a good time.
EDIT: I've noticed adding this registry setting breaks the WebBrowser.ScrollBarsEnabled
property. Despite it being false, I now have a vertical scrollbar in all of my screenshots. This happens in both versions of the screenshot generator.
In my investigations I came across the GeckoFX control. It's a Firefox browser control that can be placed in Windows Forms applications the same way the WebBrowser
control can. Unfortunately it doesn't like multithreading very much, but one guy has worked around that using processes instead of threads.
The console version of the screenshot generator suggests to me that I could place the same code inside of my MVC application, which would allow me to generate the entire Pivot collection in a single call. However, my hosting server probably doesn't have Flash installed, and it definitely won't have the registry settings required to render pages using IE8 standards mode, so it's all a moot point for now anyway.
I could use the GeckoFX control instead (sans multithreading -- probably a good thing). It's something to keep in mind if the requirement should arise.
There are 0 comments.
Older
Brisbane Flood, 2011
Newer
Lookups, Poppy's Way
Older
Brisbane Flood, 2011
Newer
Lookups, Poppy's Way
browse with Pivot
Codility Nitrogenium Challenge
OS X Lock
HACT '13
Codility Challenges
Priority Queue
Architecture (13)
ASP.NET (2)
ASP.NET MVC (13)
Brisbane Flood (1)
Building Neno (38)
C# (4)
Challenges (3)
Collections (1)
Communicator (1)
Concurrency Control (2)
Configuration (1)
CSS (5)
DataAnnotations (2)
Database (1)
DotNetOpenAuth (2)
Entity Framework (1)
FluentNHibernate (2)
Inversion of Control (5)
JavaScript (1)
jQuery (4)
Kata (2)
Linq (7)
Markdown (4)
Mercurial (5)
NHibernate (20)
Ninject (2)
OpenID (3)
OS X (1)
Pivot (6)
PowerShell (8)
Prettify (2)
RSS (1)
Spring (3)
SQL Server (5)
T-SQL (2)
Validation (2)
Vim (1)
Visual Studio (2)
Windows Forms (3)
Windows Service (1)
Comments
Leave a Comment
Please register or login to leave a comment.