2017-01-28 61 views
2

メインスレッドから呼び出す方法があります。このメソッドは新しいスレッドを作成しています。コードは次のようになります:WPFの異なるスレッドからUIコントロールを更新するときに「別のスレッドが所有しているため、このオブジェクトにアクセスできない」エラー

MouseCursorWallObject MouseCursorWall = null; 
List<MovingRectangle> MovingRectangles = null; 

DrawingImage RenderedImage; 


public MainWindow() 
    { 
     InitializeComponent(); 
     PrepareObjects();    
     GameLoopRun();      
    } 

private void GameLoopRun() 
    { 
     Thread thread = new Thread(() => 
     { 
      while (true) 
      { 
       DateTime dtStart = DateTime.Now; 

       Events(); 
       Update(); 
       Display(); 

       DateTime dtEnd = DateTime.Now; 
       TimeSpan ts = dtEnd - dtStart; 
       if (SkipTicks - ts.TotalMilliseconds >= 0) 
       { 
        Thread.Sleep((int)(SkipTicks - ts.TotalMilliseconds)); 
       } 
      } 
     }); 
     thread.Start(); 
    } 

私は更新画像コントロールを試しています。 「表示()」メソッドは次のようになります。

private void Display() 
    { 
     DrawingGroup imageDrawings = new DrawingGroup(); 

     // Drawing main canvas 
     imageDrawings.Children.Add(DrawingObject(500, 350, 0, 0, new Uri(@"Images\gameCanvas.jpg", UriKind.Relative))); 

     // Drawing mouse cursor wall 
     imageDrawings.Children.Add(DrawingObject(MouseCursorWall.Width, MouseCursorWall.Height, MouseCursorWall.GetLocX, MouseCursorWall.GetLocY, MouseCursorWall.DisplayTexture)); 

     for (int i = 0; i < MovingRectangles.Count; i++) 
     { 
      MovingRectangle o = MovingRectangles[i]; 

      // Drawing moving object 
      imageDrawings.Children.Add(DrawingObject(20, 20, o.GetLocX, o.GetLocY, o.TextureUri)); 
     } 

     if (GamePause == true) 
     { 

     } 
     RenderedImage = new DrawingImage(imageDrawings); 

     // Image control on main UI thread 
     renderImage.Dispatcher.Invoke(() => 
     { 
      renderImage.Source = RenderedImage; 
     }); 
    } 

問題はI'amがエラーを受信Dispatcher.Invoke I'amを使用して、更新Imageコントロールをしようとしたとき、別のスレッドが所有しているため、「呼び出し元のスレッドがこのオブジェクトにアクセスすることはできませんですそれ"。私は、さまざまなオプションの多くをしようとしていた、とだけは正常に動作します:「表示()」メソッドの第二の選択肢は、正常に動作する理由

private void Display() 
    { 
     this.Dispatcher.Invoke(() => { 
      DrawingGroup imageDrawings = new DrawingGroup(); 

      // Drawing main canvas 
      imageDrawings.Children.Add(DrawingObject(500, 350, 0, 0, new Uri(@"Images\gameCanvas.jpg", UriKind.Relative))); 

      // Drawing mouse cursor wall 
      imageDrawings.Children.Add(DrawingObject(MouseCursorWall.Width, MouseCursorWall.Height, MouseCursorWall.GetLocX, MouseCursorWall.GetLocY, MouseCursorWall.DisplayTexture)); 

      for (int i = 0; i < MovingRectangles.Count; i++) 
      { 
       MovingRectangle o = MovingRectangles[i]; 

       // Drawing moving object 
       imageDrawings.Children.Add(DrawingObject(20, 20, o.GetLocX, o.GetLocY, o.TextureUri)); 
      } 

      if (GamePause == true) 
      { 

      } 

      RenderedImage = new DrawingImage(imageDrawings); 
      renderImage.Source = RenderedImage; 
     }); 

    } 

あなたは私に説明してもらえますが、最初のものは例外をスロー?私は間違って何をしていますか?

+0

私はすでにそのトピックを発見しました。 – Shagohad

+0

最初にDrawingImageを.Freeze()した場合の最初の例を得ることができるかもしれませんが、おそらくUIスレッドで作成するべきです(2番目の例のように)。 – Dutts

答えて

3

DrawingImageDrawingGroupの両方がDispatcherObjectから継承されます。つまり、作成されたスレッドからアクセスする必要があります。そのため、すべての作業がディスパッチャに呼び出されたバージョンが正しく動作します。

Brian Reichle氏が指摘しているように、これらのオブジェクトは、System.Windows.Freezableも継承しています。このオブジェクトを利用すると、オブジェクトへのクロススレッドアクセスが可能になります。

+0

あなたの返信ありがとう!私は今それをチェックするつもりです。 – Shagohad

+1

"... DispatcherObjectから継承します。つまり、作成されたスレッドからアクセスする必要があります。 ...彼らが凍ってしまうことがない限り。 –

関連する問題