2

1/12 秒ごとにフレームをロードする MonoTouch アプリケーションがあります。私はopenglではなくUIkitを使用しています。私はUIImageビューを持っており、バックグラウンドタスクで画像をロードしています。

すべて問題ありませんが、1 分後 (多かれ少なかれ)、アプリケーションが停止し、トレーサーが「メモリ不足」を示します。

エミュレータでは問題なく動作します。プロファイラーを見ているとメモリが破棄されているようですが、iPadで試してみると.... :(

を使用してメモリを解放しますimage.Dispose()。メモリには 2 つの画像があり、そのうちの 1 つを表示してから、古いものをリリースしています。Windows Phone にも同じロジックがあり、正常に動作するため、この動作は問題ありません。

backgroundTask を使用せず、メイン スレッドから直接画像をロードしようとしました。それは私にもっと時間を与えます!!! backgroundTask を使用すると、アプリケーションは 30 秒間実行されてから終了します。backgroundTask を使用しない場合、1 分間続きます。

どうしたらいいのかわからない!!!! 誰でも私を助けてもらえますか?

ありがとう!!!

Texture2D.FromStream UIImage.FromFile の単なるラッパーです

これはバックグラウンド ワーカーです。

  void LoadTextureInBackground()
    {
        if (currentMovie == null) return;

        DateTime timeOnstart = DateTime.Now;

        // Mantenemos 2 texturas en memoria para no cargar sobre el mismo objeto texture.
        string fileName = currentMovie.GetFileName();

        if (lastFileName == fileName) return;

        textureLoaded[currentTexture] = Texture2D.FromStream(Device.GraphicsDevice, fileName);

        texture = textureLoaded[currentTexture];

        currentTexture = 1 - currentTexture;

        lastFileName = fileName;

        GC.Collect();
        System.Threading.Thread.Sleep(50);
    }

これは描画方法です:

    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    public void Draw(TimeSpan totalTime,TimeSpan elapsedTime)
    {
        if(currentMovie==null) return;

       // Mantenemos 2 texturas en memoria para no cargar sobre el mismo objeto texture.

        if (texture == null) return;

        int newWidth = (int)(texture.Width*RenderSize);
        int newHeight = (int)(texture.Height*RenderSize);

        Texture2D drawTexture = texture;

        // Al cargar usando Texture2D.FromStream, la textura NO lleva elAlpha premultiplicado

        //Device.SpriteBatch.Draw(drawTexture, destination, Color.White);
        if(CultTravel.AppDelegate.ImagePng.Image!=drawTexture.Texture)
        {
            AppDelegate.ImagePng.Image=drawTexture.Texture;
            AppDelegate.ImagePng.Frame=new System.Drawing.RectangleF(0,480-newHeight,ImagePng.Image.CGImage.Width,newHeight);

        // Si la textura que tengo cargada y lista para mostrar es diferente a la que mostraba, libero la antigua
        if (lastTextureDraw!=null && lastTextureDraw != texture)
        {
            lastTextureDraw.Dispose();
        }

        lastTextureDraw = texture;

    }

注: 問題を解決したところですが、バックグラウンド ワーカーを無効にし、Draw メソッドに読み込みコードを追加し、メイン スレッドに GC.Collect を追加する必要があります。

       if (lastTextureDraw!=null && lastTextureDraw != texture)
        {
            lastTextureDraw.Dispose();
            // I MUST ADD THIS TO WORK AND DISABLE THE BACKGROUND TASK!!
            GC.Collect();
        }
4

2 に答える 2

1

問題を解決しましたが、バックグラウンドワーカーを無効にし、Drawメソッドに読み込みコードを追加し、メインスレッドにGC.Collectを追加する必要があります。

   if (lastTextureDraw!=null && lastTextureDraw != texture)
    {
        lastTextureDraw.Dispose();
        // I MUST ADD THIS TO WORK AND DISABLE THE BACKGROUND TASK!!
        GC.Collect();
    }

したがって、スレッドを操作するときに問題が発生します。

于 2012-04-24T18:18:32.757 に答える
0

エミュレータでは問題なく動作します。

これはエミュレータではなくシミュレータです。そのため、メモリ制限を含め、特定のデバイスを模倣しようとはしません。IOW iOS シミュレーターは、iPad よりもはるかに多くのメモリにアクセスできます (第 1 世代 256MB、第 2 世代 512MB、第 3 世代 1GB)。

私はプロファイラーを見ています

どれ ?MonoDevelop の HeapShot または Apple の Instruments ?

image.Dispose() を使用してメモリを解放します。

それは良い考えですが、管理された側でしか機能しません。たとえば、一部の API は画像をキャッシュしますが、そのメモリはマネージ メモリではない (ネイティブに割り当てられたメモリ) ため、HeapShot には表示されません。Apple の Instruments を使用すると、これを追跡できる可能性が高くなります。

それは何か他のものである可能性もあります...つまり、@ Jonathan.Peppersが尋ねたように、画像をどのようにロードしているかを見ると、何が問題なのかを理解するのに役立ちます.

于 2012-04-23T14:05:27.127 に答える