2

WPF アプリケーションをシャットダウンすると、不可解な破棄されたオブジェクトの問題に直面しています。私の論理に間違いを見つけたら、指摘してください。

以下に示すように、メソッドを持つColorManagerクラスがあります。update()

public void Update(ColorImageFrame frame)
{
    byte[] pixelData = new byte[frame.PixelDataLength];

    frame.CopyPixelDataTo(pixelData);

    if (Bitmap == null)
    {
        Bitmap = new WriteableBitmap(frame.Width,
                                     frame.Height,
                                     96,
                                     96,
                                     PixelFormats.Bgr32,
                                     null);
    }
    // draw bitmap

    RaisePropertyChanged(() => Bitmap);   
}

このメソッドは別のスレッドで実行します。私のMainWindow.xaml.cs中で私は次のものを持っています:

    private void Initialise()
    {
        if (kinectSensor == null)
            return;
        // start kinect sensor        
        kinectSensor.Start();

        updateColourStreamThread = new Thread(new ThreadStart(colorStreamDisplay));
        updateColourStreamThread.Name = "updateColourStreamThread";
        updateColourStreamThread.Start();

        // ...some more codes
     }

        void colorStreamDisplay()
        {
            while(isDisplayActive)
            {
                using (var frame = kinectSensor.ColorStream.OpenNextFrame(500))
                {
                    if (frame == null) continue;

                    if (displayDepthStream) continue;

                    Dispatcher.Invoke(new Action(() => colorManager.Update(frame)));
                }
            }
        }

MainWindow.xaml.cs閉じるボタンをクリックした後にクリーンアップを行うには、次の方法があります。

    private void Clean()
    {
        isDisplayActive = false;
        // some other codes

        if (kinectSensor != null)
        {
            updateColourStreamThread.Abort();
            updateDepthStreamThread.Abort();
            updateSkeletonStreamThread.Abort();

            kinectSensor.Stop();
            kinectSensor = null;
            Console.WriteLine("Closed successfully");
        }

frame.CopyPixelDataTo(pixelData);閉じるボタンをクリックすると、アプリケーションが「破棄されたオブジェクトにアクセスできません」をスローします。

bool 値を false に切り替えてループを停止してから、スレッドを中止し、kinect デバイスを停止します。

私は何を取りこぼしたか?

4

1 に答える 1

4

ブール値を false に設定すると、アプリケーションは while ループを終了します。

1) boolfalse に設定する

        isDisplayActive = false;

2) このループを終了します。

        while(isDisplayActive)
        {
            using (var frame = kinectSensor.ColorStream.OpenNextFrame(500))
            {
                if (frame == null) continue;
                if (displayDepthStream) continue;

                Dispatcher.Invoke(new Action(() => colorManager.Update(frame)));
            }
        }

3) したがって、フレームも範囲外になります。ということで処分することに…。

using (var frame = kinectSensor.ColorStream.OpenNextFrame(500))

4)メインスレッドがまだ実行されていない間Thread.Abort

5) したがって、CopyPixelDataTo既に破棄されたframeオブジェクトに対して実行されます。

frame.CopyPixelDataTo(pixelData);

6)そしてkaboom、あなたのオブジェクトは例外を破棄しました。


Thread.Abort は悪い考えです。

実行中のスレッドが実行される前にどれだけ離れていたかはわかりません。これにより、あらゆる種類の厄介な副作用が発生する可能性があります。この Q&A で詳細をお読みください: Thread.Abort() を使用することの何が問題なのか

あなたの状況で私がすることは、

while(isDisplayActive)

のようなもので

while(colorThingyThreadIsBusy)

準備ができたら (=処理が完了したら) 、 colorThingyThreadBusybool を false に設定します。Thread

アプリケーションを適切に閉じるには、スレッドを中止する代わりにCancellationTokenを実装します。

于 2013-02-18T20:44:15.520 に答える