2013-06-07 2 views
7

WPF에서 메시지 루프가 유휴 상태 일 때마다 계속 실행되는 루프를 만들 수 있습니까?WPF에서 렌더링 루프를 만드는 방법은 무엇입니까?

여기서 목표는 사용 가능한 무료 리소스를 모두 사용할 수 있지만 UI를 고정시키지 않거나 메시지의 다른 작업보다 우선 순위를 두어서는 안되는 PicktureBox을 새로 고치는 것과 같이 오래 실행되는 그래픽 업데이트를 수행하는 것입니다 열.

winforms 응용 프로그램에서이 작업을 수행하는 코드를 제공하는 this blog post이 발견되었지만 WPF 응용 프로그램으로 변환하는 방법을 모르겠습니다.

using System; 
using System.Runtime.InteropServices; 
using System.Threading; 
using System.Windows.Forms; 

namespace Utilities.UI 
{ 
    /// <summary> 
    /// WinFormsAppIdleHandler implements a WinForms Render Loop (max FPS possible). 
    /// Reference: http://blogs.msdn.com/b/tmiller/archive/2005/05/05/415008.aspx 
    /// </summary> 
    public sealed class WinFormsAppIdleHandler 
    { 
     private readonly object _completedEventLock = new object(); 
     private event EventHandler _applicationLoopDoWork; 

     //PRIVATE Constructor 
     private WinFormsAppIdleHandler() 
     { 
      Enabled = false; 
      SleepTime = 10; 
      Application.Idle += Application_Idle; 
     } 

     /// <summary> 
     /// Singleton from: 
     /// http://csharpindepth.com/Articles/General/Singleton.aspx 
     /// </summary> 
     private static readonly Lazy<WinFormsAppIdleHandler> lazy = new Lazy<WinFormsAppIdleHandler>(() => new WinFormsAppIdleHandler()); 
     public static WinFormsAppIdleHandler Instance { get { return lazy.Value; } } 

     /// <summary> 
     /// Gets or sets if must fire ApplicationLoopDoWork event. 
     /// </summary> 
     public bool Enabled { get; set; } 

     /// <summary> 
     /// Gets or sets the minimum time betwen ApplicationLoopDoWork fires. 
     /// </summary> 
     public int SleepTime { get; set; } 

     /// <summary> 
     /// Fires while the UI is free to work. Sleeps for "SleepTime" ms. 
     /// </summary> 
     public event EventHandler ApplicationLoopDoWork 
     { 
      //Reason of using locks: 
      //http://stackoverflow.com/questions/1037811/c-thread-safe-events 
      add 
      { 
       lock (_completedEventLock) 
        _applicationLoopDoWork += value; 
      } 

      remove 
      { 
       lock (_completedEventLock) 
        _applicationLoopDoWork -= value; 
      } 
     } 

     /// <summary> 
     /// FINALMENTE! Imagem ao vivo sem travar! Muito bom! 
     /// </summary> 
     /// <param name="sender"></param> 
     /// <param name="e"></param> 
     private void Application_Idle(object sender, EventArgs e) 
     { 
      //Try to update interface 
      while (Enabled && IsAppStillIdle()) 
      { 
       OnApplicationIdleDoWork(EventArgs.Empty); 
       //Give a break to the processor... :) 
       //8 ms -> 125 Hz 
       //10 ms -> 100 Hz 
       Thread.Sleep(SleepTime); 
      } 
     } 

     private void OnApplicationIdleDoWork(EventArgs e) 
     { 
      var handler = _applicationLoopDoWork; 
      if (handler != null) 
      { 
       handler(this, e); 
      } 
     } 

     /// <summary> 
     /// Gets if the app still idle. 
     /// </summary> 
     /// <returns></returns> 
     private static bool IsAppStillIdle() 
     { 
      bool stillIdle = false; 
      try 
      { 
       Message msg; 
       stillIdle = !PeekMessage(out msg, IntPtr.Zero, 0, 0, 0); 
      } 
      catch (Exception e) 
      { 
       //Should never get here... I hope... 
       MessageBox.Show("IsAppStillIdle() Exception. Message: " + e.Message); 
      } 
      return stillIdle; 
     } 

     #region Unmanaged Get PeekMessage 
     // http://blogs.msdn.com/b/tmiller/archive/2005/05/05/415008.aspx 
     [System.Security.SuppressUnmanagedCodeSecurity] // We won't use this maliciously 
     [DllImport("User32.dll", CharSet = CharSet.Auto)] 
     public static extern bool PeekMessage(out Message msg, IntPtr hWnd, uint messageFilterMin, uint messageFilterMax, uint flags); 

     #endregion 
    } 
} 
+1

귀하의 질문은 자체 포함되어야합니다. 우리는 어떤 연결을 따를 필요없이 대답 할 수 있어야합니다. – Servy

+0

죄송합니다. 보스, 괜찮습니까? – Pedro77

+0

당신이하고 싶은 것이 무엇인지를 설명하는 것은 코드를 보여주는 것보다 더 중요 할 것입니다. 물론 이것은 단순한 링크보다 낫지 만 말입니다. – Servy

답변

10

이 작업을 수행하는 가장 좋은 방법은 정적 CompositionTarget.Rendering 이벤트에 의해 제공되는 프레임 당 콜백을 사용하는 것입니다 : 다음은 윈폼의 코드는 내가 다른 기사를 기반으로 만든 루프 클래스는 렌더링입니다.

+0

고맙습니다. 이동하는 것이 좋습니다. – Pedro77

관련 문제