2011-05-16 2 views
1

ImageAnimator 객체를 처음으로 사용하여 StopAnimate() 호출이 기본 스레드가 실행되지 않도록하고 StopAnimate FrameChanged 핸들러를 호출한다.ImageAnimator.StopAnimate()가 실제로 아무 것도 수행하지 않는 것 같습니다.

나는 이것을 설명하기위한 테스트를 만들었고 ImageAnimator 경험이있는 사람이라면 StopAnimate() 메소드가 실제로 수행해야하는 작업에 약간의 빛을 줄 수 있는지 궁금합니다. MSDN은 애니메이션을 멈춰야한다고 말하고 있지만 그렇지 않습니다.

업데이트를 처리 할 때 bool을 사용하여 제어 할 수 있다는 것을 알았지 만 해결 방법은 StopAnimate() 메서드가 중복 된 경우 (작업 한 경우)합니다.

using System; 
using System.IO; 
using System.Threading; 
using System.Drawing; 

namespace ImageAnimatorDemo 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      AnimateGif(); 
     } 

     private static void AnimateGif() 
     { 
      Image testImage = null; 
      using (MemoryStream stream = new MemoryStream(Convert.FromBase64String(GifData))) 
      { 
       testImage = Image.FromStream(stream); 
      } 

      ImageAnimator.Animate(testImage, delegate(object o, EventArgs args) 
      { 
       // Each time the frame is updated this will fire 
       Console.WriteLine("Tick"); 
      }); 

      Thread.Sleep(750); 

      // The following code should stop the "animation" for the supplied image which I would 
      // THINK would stop the frame changed callback from firing... 
      Console.WriteLine("Stop requested, should not see more \"Ticks\"..."); 
      ImageAnimator.StopAnimate(testImage, delegate(object o, EventArgs args) 
      { 
       Console.WriteLine("Stopped"); 
      }); 

      Console.ReadLine(); 
     } 

     private static string GifData = 
      "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"; 
    } 
} 

답변

2

내가 클래스를 디 컴파일하고 ImageAnimator 스레드 노동자 시작하는 것을 발견 :

/// <devdoc> 
    ///  Worker thread procedure which implements the main animation loop. 
    ///  NOTE: This is the ONLY code the worker thread executes, keeping it in one method helps better understand 
    ///  any synchronization issues. 
    ///  WARNING: Also, this is the only place where ImageInfo objects (not the contained image object) are modified, 
    ///  so no access synchronization is required to modify them. 
    /// </devdoc> 
    [SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals")] 
    static void AnimateImages50ms() { 
     Debug.Assert(imageInfoList != null, "Null images list"); 

     while(true) { 
      // Acquire reader-lock to access imageInfoList, elemens in the list can be modified w/o needing a writer-lock. 
      // Observe that we don't need to check if the thread is waiting or a writer lock here since the thread this 
      // method runs in never acquires a writer lock. 
      rwImgListLock.AcquireReaderLock(Timeout.Infinite); 
      try { 
       for (int i=0;i < imageInfoList.Count; i++) { 
        ImageInfo imageInfo = imageInfoList[i]; 

        // Frame delay is measured in 1/100ths of a second. This thread 
        // sleeps for 50 ms = 5/100ths of a second between frame updates, 
        // so we increase the frame delay count 5/100ths of a second 
        // at a time. 
        // 
        imageInfo.FrameTimer += 5; 
        if (imageInfo.FrameTimer >= imageInfo.FrameDelay(imageInfo.Frame)) { 
         imageInfo.FrameTimer = 0; 

         if (imageInfo.Frame + 1 < imageInfo.FrameCount) { 
          imageInfo.Frame++; 
         } 
         else { 
          imageInfo.Frame = 0; 
         } 

         if(imageInfo.FrameDirty){ 
          anyFrameDirty = true; 
         } 
        } 
       } 
      } 
      finally { 
       rwImgListLock.ReleaseReaderLock(); 
      } 

      Thread.Sleep(50); 
     } 
    } 

그것이 그렇지 않은 시작되면 여기

몇 가지 테스트 코드가 필요없는 외부 자원이다 그걸 막을 수있는 방법이있는 것처럼 보입니다. 실제로는 매우 진절머리 나는 것입니다.

+0

작은 코드 서식, 오타 및 맞춤법 오류 또한 흥미 롭습니다. 나는 MS가 모든 코드를 검토하고 완벽하게 정리했다고 생각한다. 나는 냉소적이지 않다. –

0

애니메이션 GIF 이미지가있는 PictureBox 컨트롤로 인해 응용 프로그램이 종료 될 수있는 문제가있었습니다.

범인은 정적 (사실) 루프에있는 스레드를 만드는 정적 ImageAnimator 클래스입니다.

다행히 ImageAnimator는 사용 된 스레드를 개인 필드로 설정합니다. 리플렉션으로 액세스하고 중단 할 수 있으며 애니메이션을 중지합니다.

여기 내 코드가 스레드를 중단하고 애니메이션이 중지됩니다.


    try 
    { 
     var type = typeof(ImageAnimator); 
     var info = type.GetField("animationThread", BindingFlags.NonPublic | BindingFlags.Static); 
     if (info != null) 
     { 
      var value = info.GetValue(null); 
      var thread = value as Thread; 
      if (thread != null && thread.IsAlive) 
      { 
       thread.Abort(); 
      } 
     } 
    } 
    catch{} 
관련 문제