2012-04-14 2 views
0

방금 ​​스크린 샷을 얻으려고 간단한 응용 프로그램 을 만들었습니다.WPF 응용 프로그램이 움직일 때 얼어 붙습니다.

중요한 문제는 이동했을 때 응용 프로그램이 정지한다는 것입니다.

그래서 주요 목표는 내가 여기에 모든 코드를 넣어이 스크린 샷, 스레드의 영향 등

을 가지고하는 것입니다 그렇게 u는 그것을 재현 할 수 있습니다 작동합니다.

다음은이 코드의 .NET 프로파일 링 정보입니다.

enter image description here

enter image description here

나는 그것을 고칠 수 어떻게 어떤 단서 ?

XAML

<Window x:Class="Screenshot.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded" > 
    <Grid Height="Auto"> 
     <Image Name="Image1"/> 
    </Grid> 
</Window> 

C#

public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent();    
     } 

     ScreenGrabber grabber; 

     private void Window_Loaded(object sender, RoutedEventArgs e) 
     { 
      grabber = new ScreenGrabber(5); 
      grabber.Changed += new ChangedEventHandler(grabber_Changed); 
     } 

     void grabber_Changed(object sender, EventArgs e) 
     { 
      Image1.Dispatcher.Invoke(new Action(() => { 
       BitmapSource bs = ((ScreenGrabber)sender).GetImage(); 
       Image1.Width = bs.Width; 
       Image1.Height = bs.Height; 
       Image1.Source = bs; 
      })); 
     } 
    } 

C# DLL

namespace MyScreenGrabber 
{ 
    public delegate void ChangedEventHandler(object sender, EventArgs e); 

    public class ScreenGrabber : Window 
    { 
     public event ChangedEventHandler Changed; 

     protected virtual void OnChanged(EventArgs e) 
     { 
      if (Changed != null) 
       Changed(this, e); 
     } 

     byte[] BitmapData { set; get; } 

     int Interval { set; get; } 

     DispatcherTimer Timer { set; get; } 

     public ScreenGrabber(int interval) 
     { 
      Interval = interval; 
      Timer = new DispatcherTimer(); 
      Timer.Interval = new TimeSpan(0, 0, Interval); 
      Timer.Tick += new EventHandler(Timer_Tick); 
      Timer.Start(); 
     } 

     void Timer_Tick(object sender, EventArgs e) 
     { 
      WindowInteropHelper windowInteropHelper = windowInteropHelper = new WindowInteropHelper(this); 
      Screen screen = Screen.FromHandle(windowInteropHelper.Handle); 

      using (MemoryStream ms = new MemoryStream()) 
      { 
       if (screen != null) 
       { 
        using (Bitmap bitmap = new Bitmap(screen.Bounds.Size.Width, screen.Bounds.Size.Height)) 
        { 
         using (Graphics g = Graphics.FromImage(bitmap)) 
         { 
          g.CopyFromScreen(screen.Bounds.X, screen.Bounds.Y, 0, 0, screen.Bounds.Size, CopyPixelOperation.SourceCopy); 
         } 
         ImageCodecInfo myImageCodecInfo; 
         myImageCodecInfo = GetEncoderInfo("image/jpeg"); 
         System.Drawing.Imaging.Encoder myEncoder; 
         myEncoder = System.Drawing.Imaging.Encoder.Quality; 
         EncoderParameters encoderParameters = new EncoderParameters(); 
         EncoderParameter encoderParameter = new EncoderParameter(myEncoder, 25L); 
         encoderParameters.Param[0] = encoderParameter; 
         bitmap.Save(ms, myImageCodecInfo, encoderParameters); 
         BitmapData = ms.ToArray(); 
         OnChanged(EventArgs.Empty); 
        } 
       } 
      } 
     } 

     static ImageCodecInfo GetEncoderInfo(String mimeType) 
     { 
      int j; 
      ImageCodecInfo[] encoders; 
      encoders = ImageCodecInfo.GetImageEncoders(); 
      for (j = 0; j < encoders.Length; ++j) 
      { 
       if (encoders[j].MimeType == mimeType) 
        return encoders[j]; 
      } 
      return null; 
     } 

     public BitmapSource GetImage() 
     { 
      using (MemoryStream ms = new MemoryStream(this.BitmapData)) 
      { 
       var decoder = BitmapDecoder.Create(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad); 
       return decoder.Frames[0]; 
      } 
     } 
    } 
} 

최적화 된 코드 :

,

답변

2

배경 작업자 프로세스를 사용하여 스크린 샷을 취하는 기능을 실행하면이 문제를 피할 수 있다고 생각합니다.

배경 작업자가 다른 스레드를 사용하고 주 스레드가 계속 UI를 렌더링하기 때문에 멈추지 않아야합니다.

편집 : // 나는 그래서 Background Workers VS Delegates

행운에 일을 명확히 수에이 질문을 발견!

+1

좋은 포인트 맨! 방금 배경 작업자를 추가했는데 완벽하게 작동합니다. –

관련 문제