public Yield thumb(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     var slide = context.GetParam<int>("slide");
     var width = context.GetParam<int>("width");
     var height = context.GetParam<int>("height");
     var requestInfo = new RequestInfo { 
         slide=slide,
         width=width,
         height=height
     };
     var image = cache.ContainsKey(requestInfo) ?
         cache[requestInfo] : createImage(requestInfo);
     response.Return(DreamMessage.Ok(MimeType.JPEG, image));
     yield break;
 }
 private byte[] createImage(RequestInfo info){
     byte[] result = new byte[0];
     var synchrony = new Thread(new ParameterizedThreadStart(delegate{
         List<PreParser> parserList = new List<PreParser>();
         MeTLLib.MeTLLibEventHandlers.PreParserAvailableEventHandler parserReceiver = (sender, parserAvailableArgs)=>{
             parserList.Add(parserAvailableArgs.parser);
         };
         client.events.PreParserAvailable += parserReceiver;
         var staThread = new Thread(new ParameterizedThreadStart(delegate{
             while (parserList.Count() < 3)
             { }
             var canvas = new InkCanvas();
             foreach (var preParser in parserList.ToList())
                 preParser.Populate(canvas);
             var viewBox = new Viewbox();
             viewBox.Stretch = Stretch.Uniform;
             viewBox.Child = canvas;
             viewBox.Width = info.width;
             viewBox.Height = info.height;
             var size = new Size(info.width, info.height);
             viewBox.Measure(size);
             viewBox.Arrange(new Rect(size));
             viewBox.UpdateLayout();
             viewBox.Dispatcher.Invoke(DispatcherPriority.Background,new ThreadStart(delegate { }));
             RenderTargetBitmap targetBitmap =
                new RenderTargetBitmap(info.width, info.height, 96d, 96d, PixelFormats.Pbgra32);
             targetBitmap.Render(viewBox);
             PngBitmapEncoder encoder = new PngBitmapEncoder();
             encoder.Frames.Add(BitmapFrame.Create(targetBitmap));
             using (var stream = new MemoryStream())
             {
                 encoder.Save(stream);
                 result = stream.ToArray();
             }
             client.events.PreParserAvailable -= parserReceiver;
         }));
         staThread.SetApartmentState(ApartmentState.STA);
         staThread.Start();
         client.AsyncRetrieveHistoryOf(info.slide);
         staThread.Join();
     }));
     synchrony.Start();
     synchrony.Join();
     cache[info] = result;
     return result;
 }
 private byte[] createImage(RequestInfo info){
     var provider = info.server == "madam" ? staging : prod;
     ManualResetEvent waitHandler = new ManualResetEvent(false);
     byte[] result = new byte[0];
     var synchrony = new Thread(new ThreadStart(delegate{
         provider.Retrieve<PreParser>(
             null, null,
             parser =>
             {
                 result = parserToInkCanvas(parser, info);
                 waitHandler.Set();
             }
             , info.slide.ToString());
     }));
     synchrony.Start();
     waitHandler.WaitOne();
     cache[info] = result;
     return result;
 }
 private byte[] parserToInkCanvas(PreParser parser, RequestInfo info) { 
     ManualResetEvent waitHandler = new ManualResetEvent(false);
     byte[] result = new byte[0];
     var staThread = new Thread(new ParameterizedThreadStart(delegate
     {
         try
         {
             var canvas = new InkCanvas();
             parser.Populate(canvas);
             var viewBox = new Viewbox();
             viewBox.Stretch = Stretch.Uniform;
             viewBox.Child = canvas;
             viewBox.Width = info.width;
             viewBox.Height = info.height;
             var size = new Size(info.width, info.height);
             viewBox.Measure(size);
             viewBox.Arrange(new Rect(size));
             viewBox.UpdateLayout();
             RenderTargetBitmap targetBitmap =
                new RenderTargetBitmap(info.width, info.height, 96d, 96d, PixelFormats.Pbgra32);
             targetBitmap.Render(viewBox);
             PngBitmapEncoder encoder = new PngBitmapEncoder();
             encoder.Frames.Add(BitmapFrame.Create(targetBitmap));
             using (var stream = new MemoryStream())
             {
                 encoder.Save(stream);
                 result = stream.ToArray();
             }
         }
         catch (Exception e) {
             Trace.TraceInformation("{0}\n{1}", e.Message, e.StackTrace);
         }
         finally { 
             waitHandler.Set();
         }
     }));
     staThread.SetApartmentState(ApartmentState.STA);
     staThread.Start();
     waitHandler.WaitOne();
     return result;
 }