2017-01-28 1 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(); 
    } 

이미지 컨트롤을 업데이트하려고합니다. "표시()"방법은 다음과 같습니다 I'am 다른 스레드가 소유하고 있기 때문에이 개체에 액세스 할 수 없습니다 "호출 스레드를 Dispatcher.Invoke I'am 수신 오류를 사용하여 업데이트 이미지 컨트롤을하려고 할 때

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; 
     }); 
    } 

문제는 그것". 나는 다른 선택의 여지를 시도하고 있었다, 단 하나의 잘 작동합니다 : "표시()"메소드의 두 번째 옵션은 잘 작동하는 이유

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; 
     }); 

    } 

당신은 나를 설명 할 수 있지만 첫 번째 예외를 throw? 내가 뭐 잘못 했니?

+0

이미 해당 주제가 발견되었습니다. – Shagohad

+0

그래, 먼저 DrawingImage를 .Freeze()하면 첫 번째 예제를 얻을 수 있지만 두 번째 예제에서와 같이 UI 스레드에서 만들어야합니다. – Dutts

답변

3

DrawingImageDrawingGroupDispatcherObject에서 상속됩니다. 즉, 생성 된 스레드에서 액세스해야합니다. 그래서 모든 작업이 운영자에게 다시 호출되는 버전이 올바르게 작동합니다.

Brian Reichle에 의해 지적 된 바와 같이이 객체는 System.Windows.Freezable에서 상속되기 때문에 객체에 대한 크로스 스레드 액세스를 허용 할 수 있습니다.

+0

답장을 보내 주셔서 감사합니다. 이제 확인하러 갈거야. – Shagohad

+1

"... DispatcherObject에서 상속합니다. 즉, 생성 된 스레드에서 액세스해야합니다." ... 그들이 얼지 않는 한. –

관련 문제