2011-05-16 69 views
1

我第一次使用ImageAnimator對象,並發現對StopAnimate()的調用似乎並未實際停止運行底層線程,調用FrameChanged處理程序。ImageAnimator.StopAnimate()似乎沒有實際執行任何操作

我已經創建了一個測試來說明這一點,我想知道是否任何具有ImageAnimator體驗的人都可以對StopAnimate()方法實際應該做的事情有所瞭解。 MSDN表示它應該停止動畫,但它不會。

我意識到我可以使用布爾來控制何時處理更新,但他是一種解決方法,並使(如果它的工作)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會將所有的代碼審查完畢並清理乾淨。我也不是諷刺。 – 2011-07-15 02:25:29

0

我有一個問題,其中帶有動畫gif圖像的PictureBox控件會導致應用程序退出時掛起。

罪魁禍首是靜態ImageAnimator類創建一個在while(true)循環中的線程。

幸運的是,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{}