2010-06-12 4 views
0

ASP.NET MVC 2 앱에서 WebBrowser 컨트롤을 사용하고 있습니다. (판단하지 말고, 관리자 섹션에서 저만 사용합니다), 여기 있습니다. 코드 :WebBrowser 컨트롤이 스크린 샷을 캐싱하는 것 같습니다.

public static class Screenshot 
    { 
     private static string _url; 
     private static int _width; 
     private static byte[] _bytes; 

     public static byte[] Get(string url) 
     { 
      // This method gets a screenshot of the webpage 
      // rendered at its full size (height and width) 
      return Get(url, 50); 
     } 

     public static byte[] Get(string url, int width) 
     { 
      //set properties. 
      _url = url; 
      _width = width; 
      //start screen scraper. 
      var webBrowseThread = new Thread(new ThreadStart(TakeScreenshot)); 
      webBrowseThread.SetApartmentState(ApartmentState.STA); 
      webBrowseThread.Start(); 
      //check every second if it got the screenshot yet. 
      //i know, the thread sleep is terrible, but it's the secure section, don't judge... 
      int numChecks = 20; 
      for (int k = 0; k < numChecks; k++) 
      { 
       Thread.Sleep(1000); 
       if (_bytes != null) 
       { 
        return _bytes; 
       } 
      } 
      return null; 
     } 

     private static void TakeScreenshot() 
     { 
      try 
      { 
       //load the webpage into a WebBrowser control. 
       using (WebBrowser wb = new WebBrowser()) 
       { 
        wb.ScrollBarsEnabled = false; 
        wb.ScriptErrorsSuppressed = true; 
        wb.Navigate(_url); 
        while (wb.ReadyState != WebBrowserReadyState.Complete) { Application.DoEvents(); } 
        //set the size of the WebBrowser control. 
        //take Screenshot of the web pages full width. 
        wb.Width = wb.Document.Body.ScrollRectangle.Width; 
        //take Screenshot of the web pages full height. 
        wb.Height = wb.Document.Body.ScrollRectangle.Height; 
        //get a Bitmap representation of the webpage as it's rendered in the WebBrowser control. 
        var bitmap = new Bitmap(wb.Width, wb.Height); 
        wb.DrawToBitmap(bitmap, new Rectangle(0, 0, wb.Width, wb.Height)); 
        //resize. 
        var height = _width * (bitmap.Height/bitmap.Width); 
        var thumbnail = bitmap.GetThumbnailImage(_width, height, null, IntPtr.Zero); 
        //convert to byte array. 
        var ms = new MemoryStream(); 
        thumbnail.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); 
        _bytes = ms.ToArray(); 
       } 
      } 
      catch(Exception exc) 
      {//TODO: why did screenshot fail? 
       string message = exc.Message; 
      } 
     } 

이이 새로운 URL의 첫 번째 URL의 스크린 샷을 저장하거나, 때로는거야, 내가 다른 URL의 후속 스크린 샷을하려고하지만 경우에, 내가 가지고 첫 번째 스크린 샷에 잘 작동 3 또는 4 URL의 스크린 샷을 저장하십시오. 저는 각 스크린 샷을 위해 WebBrowser의 새로운 인스턴스를 만들고 "using"블록과 함께 적절히 처리하고 있습니다. 왜 이런 식으로 행동하는지 생각해보십시오.

감사합니다, 저스틴

당신은 모든 액세스를 동기화하지 않을 때문에 당신은 너무 여러 요청 (그래서 여러 스레드가) 같은 URL을 탐색 할 수있는 기회를 가지고있는 현재의 URL을 저장하는 정적 필드를 사용하는

답변

0

. 하나의 스크린 샷 요청으로 하나의 스크린 샷 요청을 처리 할 동기화 된 대기열을 사용하거나 요청 당 하나의 인스턴스를 생성 할 수 있도록 전체 클래스를 비 정적으로 만드는 것을 고려해야합니다.

참고로 루프에서 대기하지 않고 AutoResetEvent 또는 다른 신호 메커니즘을 사용하여 대기를 수행하십시오.

+0

고마워요! – Justin

관련 문제