Skip to content

Commit cd2eb12

Browse files
author
ArthurHub
committed
handle image download synchronizations issues
1 parent 62e0ede commit cd2eb12

4 files changed

Lines changed: 42 additions & 27 deletions

File tree

Source/HtmlRenderer/Core/Dom/CssBoxFrame.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -420,12 +420,7 @@ private void HandlePostApiCall(object sender)
420420
{
421421
try
422422
{
423-
if (_videoImageUrl != null)
424-
{
425-
_imageLoadHandler = new ImageLoadHandler(HtmlContainer, OnLoadImageComplete);
426-
_imageLoadHandler.LoadImage(_videoImageUrl, HtmlTag != null ? HtmlTag.Attributes : null);
427-
}
428-
else
423+
if (_videoImageUrl == null)
429424
{
430425
_imageLoadingComplete = true;
431426
SetErrorBorder();
@@ -448,6 +443,12 @@ private void HandlePostApiCall(object sender)
448443
/// <param name="g">the device to draw to</param>
449444
protected override void PaintImp(RGraphics g)
450445
{
446+
if (_videoImageUrl != null && _imageLoadHandler == null)
447+
{
448+
_imageLoadHandler = new ImageLoadHandler(HtmlContainer, OnLoadImageComplete);
449+
_imageLoadHandler.LoadImage(_videoImageUrl, HtmlTag != null ? HtmlTag.Attributes : null);
450+
}
451+
451452
var rects = CommonUtils.GetFirstValueOrDefault(Rectangles);
452453

453454
RPoint offset = HtmlContainer != null ? HtmlContainer.ScrollOffset : RPoint.Empty;

Source/HtmlRenderer/Core/Handlers/ImageDownloader.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ namespace TheArtOfDev.HtmlRenderer.Core.Handlers
3030
public delegate void DownloadFileAsyncCallback(Uri imageUri, string filePath, Exception error, bool canceled);
3131

3232
/// <summary>
33-
///
33+
/// Handler for downloading images from the web.<br/>
34+
/// Single instance of the handler used for all images downloaded in a single html, this way if the html contains more
35+
/// than one reference to the same image it will be downloaded only once.<br/>
36+
/// Also handles corrupt, partial and canceled downloads by first downloading to temp file and only if successful moving to cached
37+
/// file location.
3438
/// </summary>
3539
internal sealed class ImageDownloader : IDisposable
3640
{
@@ -193,18 +197,21 @@ private void OnDownloadImageCompleted(WebClient client, Uri source, string tempP
193197
List<DownloadFileAsyncCallback> callbacksList;
194198
lock (_imageDownloadCallbacks)
195199
{
196-
callbacksList = _imageDownloadCallbacks[filePath];
197-
_imageDownloadCallbacks.Remove(filePath);
200+
if (_imageDownloadCallbacks.TryGetValue(filePath, out callbacksList))
201+
_imageDownloadCallbacks.Remove(filePath);
198202
}
199203

200-
foreach (var cachedFileCallback in callbacksList)
204+
if (callbacksList != null)
201205
{
202-
try
206+
foreach (var cachedFileCallback in callbacksList)
203207
{
204-
cachedFileCallback(source, filePath, error, cancelled);
208+
try
209+
{
210+
cachedFileCallback(source, filePath, error, cancelled);
211+
}
212+
catch
213+
{ }
205214
}
206-
catch
207-
{ }
208215
}
209216
}
210217

Source/HtmlRenderer/Core/Handlers/ImageLoadHandler.cs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -301,9 +301,14 @@ private void LoadImageFromFile(string source)
301301
{
302302
try
303303
{
304-
_imageFileStream = File.Open(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
305-
_image = _htmlContainer.Adapter.ImageFromStream(_imageFileStream);
306-
_releaseImageObject = true;
304+
var imageFileStream = File.Open(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
305+
lock (_loadCompleteCallback)
306+
{
307+
_imageFileStream = imageFileStream;
308+
if (!_disposed)
309+
_image = _htmlContainer.Adapter.ImageFromStream(_imageFileStream);
310+
_releaseImageObject = true;
311+
}
307312
ImageLoadComplete();
308313
}
309314
catch (Exception ex)
@@ -368,15 +373,18 @@ private void ImageLoadComplete(bool async = true)
368373
/// </summary>
369374
private void ReleaseObjects()
370375
{
371-
if (_releaseImageObject && _image != null)
372-
{
373-
_image.Dispose();
374-
_image = null;
375-
}
376-
if (_imageFileStream != null)
376+
lock (_loadCompleteCallback)
377377
{
378-
_imageFileStream.Dispose();
379-
_imageFileStream = null;
378+
if (_releaseImageObject && _image != null)
379+
{
380+
_image.Dispose();
381+
_image = null;
382+
}
383+
if (_imageFileStream != null)
384+
{
385+
_imageFileStream.Dispose();
386+
_imageFileStream = null;
387+
}
380388
}
381389
}
382390

Source/HtmlRenderer/Core/HtmlContainerInt.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ public void SetHtml(string htmlSource, CssData baseCssData = null)
421421
if (_root != null)
422422
{
423423
_selectionHandler = new SelectionHandler(_root);
424+
_imageDownloader = new ImageDownloader();
424425
}
425426
}
426427
}
@@ -879,8 +880,6 @@ internal void AddHoverBox(CssBox box, CssBlock block)
879880
/// </summary>
880881
internal ImageDownloader GetImageDownloader()
881882
{
882-
if (_imageDownloader == null)
883-
_imageDownloader = new ImageDownloader();
884883
return _imageDownloader;
885884
}
886885

0 commit comments

Comments
 (0)