2009-02-08 63 views
3

參照Software Project I am currently working onWPF:使用定時器在線程中構建隊列

我有下面的方法,基本上移動帆布帶定時器:

DispatcherTimer dt = new DispatcherTimer(); //global 
public void Ahead(int pix) 
    { 
      var movx = 0; 
      var movy = 0; 
      dt.Interval = TimeSpan.FromMilliseconds(5); 
      dt.Tick += new EventHandler((object sender, EventArgs e) => 
      { 
       if (movx >= pix || movy >= pix) 
       { 
        dt.Stop(); 
        return; 
       } 
       Bot.Body.RenderTransform = new TranslateTransform(movx++, movy++); 
      }); 
      dt.Start(); 
    } 
public void TurnLeft(double deg) 
    { 

     var currAngle = 0; 
     dt.Interval = TimeSpan.FromMilliseconds(5); 
     dt.Tick += new EventHandler(delegate(object sender, EventArgs e) 
     { 
      if (currAngle <= (deg - (deg * 2))) 
      { 
       dt.Stop(); 
      } 
      Bot.Body.RenderTransform = new RotateTransform(currAngle--, BodyCenter.X, BodyCenter.Y); 
     }); 
     dt.Start(); 
    } 

現在,從另一個庫,這些方法被稱爲像這樣:

public void run() 
{ 
    Ahead(200); 
    TurnLeft(90); 
} 

現在當然,我希望這些動畫在另一個之後發生,但是發生的情況是當第二種方法(在這種情況下爲TurnLeft(90))被調用時,DispatchTimerdt.Tick事件處理程序被覆蓋,因此只有第二種方法d得到執行,因爲它應該。

我需要創建某種排隊方式,這樣我就可以將方法推送到該隊列,以便dtDispatchTimer定時器)逐個執行它們......按照它們在「隊列」中的順序執行它們,

我可以這樣做嗎?我在這裏的正確軌道上,還是完全偏離?

回答

1

我自己解決了這個問題。我所做的是創建一個類型爲Delegate的全局Queue,而不是直接執行這些方法,而是將它們添加到此隊列中。

然後我會在構造一個單獨的線程將出列方法逐一執行它們:

Queue<TimerDelegate> eventQueue = new Queue<TimerDelegate>(); 

    public Vehicle(IVehicle veh, Canvas arena, Dispatcher battleArenaDispatcher) 
    { 
     DispatcherTimer actionTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(100) }; 
     actionTimer.Tick += new EventHandler(delegate(object sender, EventArgs e) 
    { 
     if (IsActionRunning || eventQueue.Count == 0) 
     { 
      return; 
     } 
     eventQueue.Dequeue().Invoke(new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(5) }); 
    }); 
    actionTimer.Start(); 
    } 

    public void TurnRight(double deg) 
    { 
     eventQueue.Enqueue((TimerDelegate)delegate(DispatcherTimer dt) 
     { 
      IsActionRunning = true; 
      var currAngle = 0; 
      dt.Tick += new EventHandler(delegate(object sender, EventArgs e) 
      { 
       lock (threadLocker) 
       { 
        if (currAngle >= deg) 
        { 
         IsActionRunning = false; 
         dt.Stop(); 
        } 
        Rotator_Body.Angle++; 
        currAngle++; 
       } 
      }); 
      dt.Start(); 
     }); 
    } 
+1

音序器!萬分感謝! – discorax 2009-10-12 17:30:50

1

當您在Dispatcher上調用Invoke()或BeginInvoke()時,操作將排隊並在與Dispatcher關聯的線程空閒時運行。因此,不要使用Tick事件,而要使用帶TimeSpan的Dispatcher.Invoke重載。

+0

但我需要Tick事件動畫的運動。 – 2009-02-08 07:16:21