2009-02-08 2 views
3

Software Project I am currently working on을 참조하십시오.WPF : 타이머가있는 스레드에서 큐 구성

나는 기본적으로 타이머와 캔버스를 이동하려면 아래의 방법이 있습니다

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 이벤트 처리기가 덮어 쓰여지고 있으므로 두 번째 metho d는 필요한대로 실행됩니다.

나는 어떤 종류의 큐를 만들어서 큐에 넣고 푸시 할 수 있도록해야한다. 따라서 dt (DispatchTimer 타이머)이 하나씩 큐를 실행한다. 큐에있는 순서대로

나는 이것을 어떻게 할 수 있습니까? 여기 오른쪽 궤도에 있습니까, 아니면 완전히 벗어 났습니까?

답변

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

1

Dispatcher에서 Invoke() 또는 BeginInvoke()를 호출하면 Dispatcher와 연관된 스레드가 비어있을 때 작업이 대기열에 올려 져 실행됩니다. 따라서 Tick 이벤트를 사용하는 대신 Timespan을 사용하는 Dispatcher.Invoke의 오버로드를 사용하십시오.

+0

을하지만 움직임을 애니메이션 틱 이벤트가 필요합니다. –

관련 문제