1

何が起こっているのかを突き止めました - 加速度計と VideoBrushes を同時に実行すると、VideoBrush がフリーズします。これを修正するには、VideoBrush を開始する前に加速度計を停止します。

最小限のコード (すぐ下に記載) を使用すると、アプリで VideoBrush が開始されてから約 2 分 15 秒で確実にクラッシュします。これは、Windows Phone 7.5 アプリ用の Windows 7 エミュレーターで、c# と Xaml を使用しています。VideoBrush ストレッチも塗りつぶしに設定されている場合などに発生します (これには Silverlight 1.0 のバグがありました)。

私がこれにどのように派生したかの話については、以下のテキストの回答の壁をチェックしてください:)

なぜこれが起こるのですか?私は知らない。もしかしてメモリーリークか何か?注 - これにより実際にアプリ自体がクラッシュすることはありません。例外がポップアップすることはありません。

問題を再現するコード (PhoneApp1 という名前の新しいアプリケーションを作成し、自分で試してください!):

Xaml コード:

<phone:PhoneApplicationPage 
    x:Class="PhoneApp1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="False">

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">

            <Rectangle x:Name="viewfinderCanvas" Width="480" Height="800" >
                <Rectangle.Fill>
                    <VideoBrush x:Name="viewfinderBrush"/>
                </Rectangle.Fill>
            </Rectangle>

    </Grid>
</phone:PhoneApplicationPage>

C# コード:

using System;
using System.Windows;
using Microsoft.Phone.Controls;
using Microsoft.Devices;
using Microsoft.Devices.Sensors;

namespace PhoneApp1
{
    public partial class MainPage : PhoneApplicationPage
    {
        private Accelerometer AccelerometerSensor;

        // Constructor
        public MainPage()
        {
            InitializeComponent();
            AccelerometerSensor = new Accelerometer();
            AccelerometerStartup();

            if ((PhotoCamera.IsCameraTypeSupported(CameraType.Primary) == true))
            {
                viewfinderCanvas.Visibility = Visibility.Visible;
                var cam = new Microsoft.Devices.PhotoCamera(CameraType.Primary);

                viewfinderBrush.SetSource(cam);
            }
        }

        #region Accelerometer Startup Function
        private void AccelerometerStartup()
        {
            try
            {
                if (AccelerometerSensor != null)
                {
                    AccelerometerSensor.Start();

                }
            }
            catch (AccelerometerFailedException)
            {
            }
            catch (UnauthorizedAccessException)
            {
            }
        }
        #endregion
    }
}

以下の元の質問: (以下のコードは保持されますが、加速度計が取り付けられていないため問題は再現しません)

これは楽しいものです、約束します。

wp7.5 アプリに、塗りつぶしプロパティが VideoBrush である四角形を配置することにしました。いくつかの Web サイトから見つけたコードを使用しましたが、すべて問題ないと思いました。これは、カメラからの VideoBrush がフリーズすることに気付くまででした... 実行してから 6 ~ 40 秒かかりました。

困惑して、ディスパッチ タイマーがカメラに干渉していると思いました。それらを実行できないようにコメントアウトしても、問題は解決しませんでした。次に、アプリで広告を無効にしてみました。また、それを修正しませんでした。アプリ全体で更新をレンダリングできるすべてのもの (タイマー、ディスパッチ タイマー、広告のローテーション、ループ) を無効にしましたが、それでもフリーズします。

Zuneを開いた状態でコンピューターに接続しているときにデバイスでデバッグを読んだときに、同じことを行い、デバイスをコンピューターから取り外しました。まだサイコロはありません。

新しいプロジェクトを作成し、VideoBrush コードだけをコピーして貼り付けたところ、フリーズすることなく動作しました。

XAML コード:

<Rectangle x:Name="viewfinderCanvas" Width="480" Height="800" Visibility="Collapsed" DoubleTap="viewfinderCanvas_DoubleTap">
            <Rectangle.Fill>
                <VideoBrush x:Name="videoBrush">
                <VideoBrush.RelativeTransform>
                    <CompositeTransform x:Name="previewTransform"
                            CenterX=".5"
                            CenterY=".5" />
                </VideoBrush.RelativeTransform>
                </VideoBrush>
            </Rectangle.Fill>
        </Rectangle>

C# コード:

if ((PhotoCamera.IsCameraTypeSupported(CameraType.Primary) == true))
    {
           viewfinderCanvas.Visibility = Visibility.Visible;
           var cam = new Microsoft.Devices.PhotoCamera(CameraType.Primary);

           if (Orientation == PageOrientation.PortraitUp || Orientation ==  
           PageOrientation.PortraitDown || Orientation == PageOrientation.Portrait)
             {
                videoBrush.RelativeTransform =
                new CompositeTransform() { CenterX = 0.5, CenterY = 0.5, Rotation = 90 };
             }

           videoBrush.SetSource(cam);
    }

本当に、この VideoBrush ディスプレイのフリーズを引き起こしている原因がわかりません。すべての関数にブレークポイントを設定しましたが、何も検出されませんでした。エラーメッセージはありません...ビデオがフリーズするだけです。

誰もこれに遭遇したことがありますか?私のデバイスと私がコーディングしているコンピューターの両方で発生します - エミュレーターのホワイトボックスが停止します。

わかりやすくするために、これはカメラがアプリで見ているものを示すことだけを目的としています。写真を撮ったり、ビデオを録画したりしているわけではありません。私はただこのショーを作っているだけです。ウィンドウを閉じるには、四角形をダブルタップして raw ビューを閉じます。

4

3 に答える 3

1

私は何が起こっているのかを発見しました。それは確かに私のコードに問題がありました。

TL:DR: アクティブな VideoBrush を持つアクティブな加速度計により、VideoBrush が最終的にフリーズします。

これをテストするために私がしたこと:

2000 行以上のコードを使って、そこに座って、API、参照、および VideoBrush がフリーズする原因になると一般的に考えられるものをコメントアウトし始めました。適切なサイズのコードのチャンクを取り出すたびにアプリをテストして、違いが生じるかどうかを確認しました。私のテストでは、VideoBrush が開始されてからフリーズするまでにかかった秒数に依存していました。

興味深いことに、何かを削除する前に、通常、VideoBrush がフリーズするまで約 45 秒かかりました。コードを切り取った後、突然 2 分 45 秒に跳ね上がったときに、最初の主要な結果が得られました。これは、Blend でアニメーション化されたいくつかのスタックパネル、テキストブロック、およびボタンを含むいくつかのグリッドを削除したときに達成されました。

この時点で、私は Blend のものが Visibility.Visible から Visibility.Collapsed に変わっていないという考えを冗談で言いました。VideoBrush を呼び出す前にすべてを折りたたむ関数は、2:45 のフリーズ時間に変化をもたらさなかったため、これは当てはまりませんでした。

すべてのアセットを取り出し、すべてのタイマー、ディスパッチ タイマー、ストップウォッチ、datetime インスタンスを取り出しましたが、それでも 2:45 を変更するために何もしませんでした。

それから私はそれに出くわしました:私の加速度計。

全体像として、2 つの異なるページで wp7 アプリケーションで加速度計を使用しています。ユーザーが初めてアプリを開くと、メイン ページを模倣する加速度計を備えたチュートリアル ページが表示されます。そのチュートリアルが完了すると、ユーザーは同じ名前の加速度計とイベント変更通知を含むメインページに移動します。

補足として、コードを調べているときに、どちらのページでも実際に加速度計を停止/配置していないコーディングエラーに気付きました。これによりアプリがクラッシュすることはなく、問題が認識されることもありませんでした。

これを修正すると、VideoBrush がフリーズする前に、時間が約 5:00 まで跳ね上がることに気付きました。進行中ですが、まだこのフリーズを引き起こしているのは何ですか?

次に、VideoBrush を開始する前に加速度計を停止することにしました。見よ、VideoBrush は画像をフリーズすることなく動作します。

アプリがクラッシュせずに VideoBrush の動作を停止する原因を知らずに回答するのは不可能な質問だったので、申し訳ありません。少なくとも、既知の方法が 1 つあります。

于 2012-11-20T06:29:49.437 に答える
0

KooKiz のコメントで述べたように、VideoBrush のフリーズを最小限のコードで再現できました。時間は異なる場合がありますが、以下のコードでは、VideoBrush は 2 分 14 秒から 2 分 15 秒の間で確実にフリーズします。(エミュレーターを実行してシステム クロックを開き、VideoBrush がいつ開始され、いつフリーズしたかを記録することで、これを複数回計測しました。)

Xaml コード:

<phone:PhoneApplicationPage 
    x:Class="PhoneApp1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="False">

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">

            <Rectangle x:Name="viewfinderCanvas" Width="480" Height="800" >
                <Rectangle.Fill>
                    <VideoBrush x:Name="viewfinderBrush"/>
                </Rectangle.Fill>
            </Rectangle>

    </Grid>
</phone:PhoneApplicationPage>

C# コード:

using System;
using System.Windows;
using Microsoft.Phone.Controls;
using Microsoft.Devices;
using Microsoft.Devices.Sensors;

namespace PhoneApp1
{
    public partial class MainPage : PhoneApplicationPage
    {
        private Accelerometer AccelerometerSensor;

        // Constructor
        public MainPage()
        {
            InitializeComponent();
            AccelerometerSensor = new Accelerometer();
            AccelerometerStartup();

            if ((PhotoCamera.IsCameraTypeSupported(CameraType.Primary) == true))
            {
                viewfinderCanvas.Visibility = Visibility.Visible;
                var cam = new Microsoft.Devices.PhotoCamera(CameraType.Primary);

                viewfinderBrush.SetSource(cam);
            }
        }


        #region Accelerometer Startup Function
        private void AccelerometerStartup()
        {
            try
            {
                if (AccelerometerSensor != null)
                {
                    AccelerometerSensor.Start();

                }
            }
            catch (AccelerometerFailedException)
            {
            }
            catch (UnauthorizedAccessException)
            {
            }
        }
        #endregion
    }
}
于 2012-11-20T17:40:32.917 に答える
0

あなたのコードのおかげで、問題を再現することができ、根本的な原因を見つけました。

準備してください、それは「...それだけですか?」になるでしょう。一瞬!

基本的に、問題全体はその行にあります。

var cam = new Microsoft.Devices.PhotoCamera(CameraType.Primary);

新しい を作成してPhotoCameraいますが、参照をどこにも保持していません。したがって、ガベージ コレクターが起動すると、孤立しPhotoCameraたインスタンスが破棄され、ビデオがフリーズします。

再現は簡単です。ページにボタンを追加し、クリック ハンドラを配置するだけです。

GC.Collect();

ボタンを押すとすぐに、ビデオがフリーズします。

ここで明らかな疑問は、なぜ加速度計だけでフリーズするのかということです。実際には非常に単純です。割り当てられたオブジェクトの総数がしきい値に達すると、ガベージ コレクションが自動的にトリガーされます。ビデオしかない場合、割り当てられるオブジェクトはほとんどない (おそらく何もない) ため、ガベージ コレクターはしばらく前にトリガーされません。加速度計をオンにすると、その位置が高速で更新され、プロセス内で新しいオブジェクトが割り当てられるため、数分後にガベージ コレクションがトリガーされます。

問題を解決するには?PhotoCamera参照をプロパティに保存するだけです。

private PhotoCamera cam;

public MainPage()
{
    InitializeComponent();

    AccelerometerSensor = new Accelerometer();
    AccelerometerSensor.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<AccelerometerReading>>(AccelerometerSensor_CurrentValueChanged);
    AccelerometerStartup();

    if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary))
    {
        viewfinderCanvas.Visibility = Visibility.Visible;
        cam = new PhotoCamera(CameraType.Primary);

        viewfinderBrush.SetSource(cam);
    }
}
于 2012-11-20T20:22:45.460 に答える