2017-11-13 2 views
0

Im WPF 응용 프로그램에서 사용하고 일부 작업을 수행하기 위해 DepthFrameReady 이벤트를 수신합니다. UI 블록을 피하기 위해 나는 async 이벤트를 만들었고 메신저는 데이터 조작을 만든 함수를 "기다리고"있습니다.비동기 이벤트에서 개체 삭제 C# WPF

Rigth 이제 메시지 점점 비주얼 스튜디오 메신저에서 출력 창에서 :

경고 : IMAGEFRAME 인스턴스 내가 DepthImageFrame (넣어 처분 할 많은 것들을 시도

배치되지 않았습니다 논리 내부 using 블록, 비동기 함수가 끝날 때 콜백 등).하지만 처음 호출 한 후에는 null을 보내고 있으므로 ...

비동기/대기 이벤트에 개체를 배치하는 가장 어려운 방법은 무엇입니까?.


MyWindow.xaml.cs

private async void KinectSensorFound_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e) 
{ 

    // as suggested in Zoran Answer 
    await Task.Run(() => 
      { 
       using (DepthImageFrame DataDepthImageFrame = e.OpenDepthImageFrame()) 
       { 
        UpdateUserDepthInfo(DataDepthImageFrame); 
       } 

      }); 
} 


public void UpdateUserDepthInfo(DepthImageFrame DataDepthImage) 
     { 
      var TimeNow = DateTime.Now; 
      if ((DateTime.Now - PreviusTime).Milliseconds <= 50) 
       return; 

      syncronizationContext.Post(new SendOrPostCallback(o => 
      { 
       if (chckbxDepthImage.IsChecked == true) 
       { 
        chckbxColorImage.IsChecked = false; 
        // This method is called in my bussines logic to do a transformation with the frame 
        BitmapSource DepthBitMapSource = Controller.getInfoOfDepthUser(DataDepthImage); 
        DepthCanvas.Background = new ImageBrush(DepthBitMapSource); 
       } 
       else 
       { 
        DepthCanvas.Children.Clear(); 
        DepthCanvas.Background = new SolidColorBrush(Colors.Transparent); 
       } 

       DepthUserInfo = Controller.DoGetInfoDepthUser(DataDepthImage); 
       lblDepthUser.Content = string.Format("{0:0.00} mts", DepthUserInfo/1000); 

      }), DataDepthImage); 
      PreviusTime = TimeNow; 
     } 

KinectHelper.cs

public BitmapSource getBitmapOfDepth(DepthImageFrame DataImageFrame) 
{ 
    DepthImagePixel[] ImageDepth = new DepthImagePixel[0]; 
    int DepthDistance; 
    depthReturnStruct DepthReturn = new depthReturnStruct(); 

    if (DataImageFrame != null) 
    { 
     ImageDepth = new DepthImagePixel[DataImageFrame.PixelDataLength]; 
     DataImageFrame.CopyDepthImagePixelDataTo(ImageDepth); // exception here 

     //... other code 
    } 
    return bitmapDepth; 
} 
+0

Task.Run을 기다린 후 dispose를 호출하지 않는 이유는 무엇입니까? – Steve

+0

스티브에게 감사 드리며 제안을 시도했지만 'DataDepthImageFrame'을 사용하는 메소드를 호출 할 때 다음 오류 (** System.ObjectDisposedException **)가 표시됩니다. –

답변

0

여기 내 느낌은 당신이 책임을 혼합하는 것입니다. 일을 분명히하기 위해, 모든 물건에는 소유자가 있어야합니다 - 소유자는 그것을 인스턴스화하고 폐기합니다. 귀하의 솔루션에서 이들은 두 개의 엔티티, 즉 DataDepthImageFrame을 구성하는 이벤트 핸들러와 작업을 수행하는 태스크입니다.

내 의견으로는, 작업을 시작하는 함수는 이미지 프레임을 생성해서는 안되며, 대신 그것에 대한 팩토리 함수를 준비해야합니다. 그러면 작업이 객체를 인스턴스화하고 처리 할 수 ​​있습니다. 그런 식으로 작업은 해당 개체에 전적인 책임이 있습니다.

물론 클로저에서 팩토리를 캡처하려는 경우에는 필요하지 않습니다. 이벤트 인수 e을 캡처하여 직접 작업에 사용할 수 있습니다.

private async void KinectSensorFound_DepthFrameReady(
    object sender, DepthImageFrameReadyEventArgs e) 
{ 
    await Task.Run(
    () => 
    { 
     using (DepthImageFrame DataDepthImageFrame = e.OpenDepthImageFrame()) 
     { 
      UpdateUserDepthInfo(DataDepthImageFrame) 
     } 
    }); 
} 

나는 당신의 시나리오를 재현 할 수없는,하지만 난 작업이 실행 시작할 때 이벤트 인수의 이미지 프레임이 다른 스레드에서 열 수 살아남을 것이라고 믿는다.

+0

고마워 Zoran, 나는 당신의 제안을 따라 갔지만 (DataImageFrame.CopyDepthImagePixelDataTo (ImageDepth);) 예외를 던졌습니다 ** System.ObjectDisposedException **, 내 코드를 더 자세히 업데이트했습니다. 스레드 컨텍스트가 엉망이 될 수 있다면 몰라요. –

관련 문제