|
Rank: Member Groups: Member
Joined: 4/8/2014 Posts: 12
|
When using Wpf.WebView.LoadHtml to load the following sample, the image from the file system (test.jpg) does not load but the http image does.
Code: C#
webview.LoadHtml(@"<html><body><img src=""file:///c:/temp/test.jpg""><img src=""http://placehold.it/350x150""></body></html>");
It works correctly when saving the html to a file and using WebView.Url to load the html file. I am wishing to use RegisterResourceHandler with the local file links, this currently works when loading a file using WebView.Url but not when using WebView.LoadHtml. Thanks Tim
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,196
|
Hi,
This is just to let you know that we are still working on this. The root of the problem has to do with same origin policy where an HTML with no origin is not allowed to access Url with "file" origin. However this restriction would render LoadHtml pretty useless. As such we are looking into adding a flag to allow you to turn this restriction off. We will post again as soon as this has been added.
Thanks!
|
|
Rank: Member Groups: Member
Joined: 4/8/2014 Posts: 12
|
Thanks for the update
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,196
|
Hi, We have posted a new build that addressed this issue. You can download the new build from our download page. With the new build, you must set browser option EnableWebSecurity to false to enable local file access: http://www.essentialobjects.com/doc/6/eo.webbrowser.browseroptions.enablewebsecurity.aspxSee here for more information on how to set browser options: http://www.essentialobjects.com/doc/6/advanced/browser_options.aspxHope this helps. Please feel free to let us know if you have any more questions. Thanks!
|
|
Rank: Member Groups: Member
Joined: 4/8/2014 Posts: 12
|
Thanks, this works fine. But...
When using LoadHtml in conjunction with a ResourceHandler, it appears to load the html very slowly (the html is a simple list of 15 images). My resource handler is matching all urls that end in ".jpg" so I can load images from a custom stream.
If I return true from ResourceHandler.Match, it takes nearly a second before the next Match call is made. If I return false from ResourceHandler.Match, the page loads almost instantly
The ResourceHandler.ProcessRequest method does not appear to be called while ResourceHandler.Match is running slowly but is called just before/as the page is displayed .
I have a simple project that demonstrates this.
Tim
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,196
|
Hi,
We have sent the instruction for the test project to you via private message. You can also click the "Submit Test Project" link at the top of the forum to view detailed instructions (you must log in in order to see this link).
Thanks!
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,196
|
Hi Tim, We have looked into the sample project you sent to us. The root of the problem is .NET ThreadPool thread creation throttling. The .NET thread pool will grow number of threads in the pool immediately as needed until it reaches a certain throttling threshold, after that threshold it will intentionally delay creation of new thread thus delaying the task submitted to the thread pool. This affects EO.WebBrowser custom resource handler since it uses thread pool to run both Match and Process. To resolve the problem, call the following code once before you create any WebView:
Code: C#
System.Threading.ThreadPool.SetMinThreads(100, 100);
The above code sets the "threshold" to 100. This does not mean the thread pool will pre-create 100 threads sitting there doing nothing. It only means as long as the total number of thread (concurrent tasks) in the thread pool is less than 100, if a new task is submitted and none of the existing thread is available, then a new thread will be created immediately. Once the total number of threads pass 100, the thread pool will introduce a delay on purpose. It was this delay that slows down the custom handler. Hope this helps. Please feel free to let us know if there is anything else. Thanks!
|
|
Rank: Member Groups: Member
Joined: 4/8/2014 Posts: 12
|
Thanks for the reply, I can confirm that this does solve the problem. However, it is not a robust solution as I would have to make the ThreadPool minimum size larger than the total number of matched resources in any one page and I have no control over this.
Unless the "matched" ProcessRequests methods are allowed to be called before all the resources are checked for matching, using a ThreadPool is not a wise choice as the Matching is always in danger of blocking as the threads cannot be freed until ProcessRequest is called.
Thanks Tim
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,196
|
Hi,
Thanks for confirming the fix. We believe using thread pool is the best solution. There is no way to precisely control/ensure all "Match" to be called before all "Process" because your page can load resources dynamically anytime, and there is no way to predict total number of concurrent tasks either. Further more, both "Match" and "Process" are treated as independent thread pool tasks, so for the same resource, "Match" and "Process" can be called by different threads from the thread pool --- the only rule is "Process" has to be called after "Match" for a given resource. So blocking one "Match" call will not block "Process" for other resources.
The reason .NET has a threshold is to prevent the system creating an extremely high number of threads thus rapidly exhaust system resource. We could implement our our thread management to handle Match and Process and we would have to implement similar threshold mechanism to prevent a run away thread creation. So in the end you would have to settle with a reasonable total number of threads available either using the .NET built-in thread pool or not.
Hope that makes sense to you. If you have any other thought please share with us.
Thanks
|
|
Rank: Member Groups: Member
Joined: 4/8/2014 Posts: 12
|
Ok, but I am still wondering, why are the match tasks not completing and freeing up threads for subsequent match tasks.
E.g., from the project I provided, a new thread is allocated for each match task regardless of the Threadpool minimum, it's just that raising the minimum removes the delay allocating a "new" thread. A similar number of managed threads appear to be created in the end.
I would expect when using a threadpool that the tasks should be shortlived and complete quickly so that the threads are released back to the pool.
Thanks Tim
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,196
|
Hi,
The tasks are short lived and the threads are indeed released to the thread pool. What you saw is a purely the delay .NET ThreadPool intentionally introduced while creating new thread. Let's say the ThreadPool only creates 1 thread without delay, the sequence of the event causing the delay would be like this:
1. Match A is submitted, a new thread X is created immediately to call this method. Say this method takes 5 milliseconds to complete; 2. Match B is submitted 2 milliseconds after step 1. At this point Match A is still not done yet since it takes 5 milliseconds. As a result, the thread pool concluded that it will need to create a new thread Y; 3. Since now the thread pool have already reached the threshold value (1), it will introduce a delay to create a new thread, let's say 1 second. So Match B will not be called until 1 second later; 4. A few milliseconds after step 2, Match A completes and now thread X becomes available. However at this point Match B is already assigned with thread Y (which will be created after a delay), so thread X now is returned to the thread pool to serve the next request. However Match B will still be delayed since it has already been associated to thread Y;
This logic does appear a little strange since step 4 the thread pool could have just reuse thread X to run Match A, but that's not what happened. However increasing the threshold will eliminate this problem. The consequence of increasing the threshold is that you will see a large number of managed thread. These thread must exist at one point in order to serve a high number of concurrent tasks (both Match and Process) at the same time. However whether they will be eventually destroyed, or whether it's a problem if they are not destroyed remain to be seen. If that turns out to be a problem, we will investigate further and may change our code to manage the threads ourselves instead of using .NET's built-in thread pool.
Thanks!
|
|
Rank: Member Groups: Member
Joined: 4/8/2014 Posts: 12
|
Thanks for the explanation.
A Threadpool that could handle a high number of concurrent tasks would be an ideal solution, especially as showing a webpage is always going to start as many concurrent tasks as it has resources.
Thanks Tim
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,196
|
You are very welcome. That's exactly why we choose to use .NET's built-in thread pool. MS has done many optimizations on it's built-in thread pool. The new Task Parallel Library in .NET 4 is also based on the built-in thread pool. So it has been extensively used and tested. The only nuisance is this thread creation delay that MS put in on purpose. So we believe using the built-in thread pool with a higher threshold value is the best solution for now. We may change our code to increase the threshold automatically in our code so that it will be one less thing for our users to worry about.
In any case please be rest assured that we are always open to optimizations and improving the product whatever way we can. So please feel free to share with us if you see any other problems or have any other thoughts about the product. User feedbacks are very important to us. We can not make a good product alone.
Thanks!
|
|