void asyncOperation_Failed(object sender, ThreadExceptionEventArgs e)
        {
            UpdateSemanticHtmlPreviewAsyncOperation asyncOperation = (UpdateSemanticHtmlPreviewAsyncOperation)sender;

            Trace.WriteLine("UpdateSemanticHtmlPreviewAsyncOperation failed for blog(" + asyncOperation.BlogId + "): " + e.Exception);

            // Note: We intentionally do not remove this async op from asyncOps in order to prevent an infinite loop of failures.
        }
        void asyncOperation_Completed(object sender, EventArgs e)
        {
            UpdateSemanticHtmlPreviewAsyncOperation asyncOperation = (UpdateSemanticHtmlPreviewAsyncOperation)sender;

            lock (Lock)
            {
                _asyncOps.Remove(asyncOperation.BlogId);
            }
        }
        internal Bitmap GetPreviewBitmap(string blogId, string elementId)
        {
            Debug.Assert(_blogPreviewInfo.ContainsKey(blogId), "Need to register blog for preview");
            Debug.Assert(((ISynchronizeInvoke)_editingSite).InvokeRequired == false, "This should only be called on the UI thread");

            string path = GetPreviewBitmapPath(blogId, elementId);

            try
            {
                lock (Lock)
                {
                    BlogPreviewInfo info = _blogPreviewInfo[blogId];

                    if (info.BitmapCached(elementId))
                    {
                        return(info.GetBitmap(elementId));
                    }
                    else if (File.Exists(path))
                    {
                        MemoryStream ms;
                        using (FileStream fs = File.OpenRead(path))
                        {
                            ms = new MemoryStream((int)fs.Length);
                            StreamHelper.Transfer(fs, ms);
                            ms.Seek(0, SeekOrigin.Begin);
                        }
                        info.SetBitmap(elementId, new Bitmap(ms));
                        return(info.GetBitmap(elementId));
                    }

                    if (!_asyncOps.ContainsKey(blogId))
                    {
                        // Fetch asynchronously
                        UpdateSemanticHtmlPreviewAsyncOperation asyncOperation = new UpdateSemanticHtmlPreviewAsyncOperation(_editingSite, blogId, info.ElementIds, info.TemplateHtml, info.PostBodyHtml, info.IsRtl, _editingSite.FrameWindow, Lock, _width, _height);
                        _asyncOps.Add(blogId, asyncOperation);

                        asyncOperation.Failed    += new ThreadExceptionEventHandler(asyncOperation_Failed);
                        asyncOperation.Completed += new EventHandler(asyncOperation_Completed);
                        asyncOperation.Start();
                    }
                    // else we're already fetching
                }
            }
            catch (Exception ex)
            {
                Trace.Fail("Failed to get preview bitmap for blog(" + blogId + ") and element(" + elementId + "): " + ex);
            }

            return(null);
        }