2013-10-28 51 views
0

我想在用戶按住某個鍵的同時在窗口中移動一個形狀。 我是新來的,所以我嘗試了這種方法,但我無法更改我的新線程中的circle.RederTransform,因爲它屬於不同的線程。應該怎麼做?在WPF中關閉時移動形狀

public partial class MainWindow : Window 
    { 
     private Matrix transformationMatrix = Matrix.Identity; 
     private Thread myThread = null; 
     private bool isGoing = false; 

     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private void Window_KeyDown(object sender, KeyEventArgs e) 
     { 
      isGoing = true; 
      myThread = new Thread(HandleMyThread); 
      myThread.Start(); 
     } 

     private void Window_KeyUp(object sender, KeyEventArgs e) 
     { 
      isGoing = false; 
     } 

     private void HandleMyThread(object obj) 
     { 
      while(isGoing) 
      { 
       transformationMatrix.Translate(10, 0); 
       circle.RenderTransform = new MatrixTransform(transformationMatrix); 
       Thread.Sleep(50); 
      } 
     } 

    } 

回答

1

在WPF中,您希望將System.Windows.Threading.DispatcherTimer類用於UI線程安全定時器。

下面是一個例子:

public partial class MainWindow : Window 
{ 
    private DispatcherTimer _timer; 

    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    protected override void OnContentRendered(EventArgs e) 
    { 
     base.OnContentRendered(e); 

     _timer = new DispatcherTimer(); 
     _timer.Interval = TimeSpan.FromMilliseconds(50); 
     _timer.Tick += timer_Tick; 

    } 

    protected override void OnKeyDown(KeyEventArgs e) 
    { 
     base.OnKeyDown(e); 

     _timer.Start(); 
    } 

    protected override void OnKeyUp(KeyEventArgs e) 
    { 
     base.OnKeyUp(e); 

     _timer.Stop(); 
    } 

    private void timer_Tick(object sender, EventArgs e) 
    { 
     transform.X += 2; 
     transform.Y += 2; 
    } 
} 
0

你可能會逃脫只要使用一個Invoke做......但有更好的方法做你想做的事情。

首先,每次處理KeyDown時創建一個線程效率低下......並且可能導致問題...因爲創建和計劃Thread ...可能需要一段時間......因此,「事情「移動。

另外,您可能會陷入混亂狀態,讓多線程存在。例如,說有人反覆按下並釋放鍵......在這種情況下,「舊」線程仍然可以繼續運行...因爲isGoing標誌爲真...換言之,同步性很差。

private void HandleMyThread(object obj) 
{ 
    Action action = new Action(()=> 
    { 
     transformationMatrix.Translate(10, 0); 
     circle.RenderTransform = new MatrixTransform(transformationMatrix); 
    }; 

    while(isGoing) 
    { 
     this.Dispatcher.Invoke(DispatcherPriority.Normal, action); 
     Thread.Sleep(50); 
    } 
}