7

当社のソフトウェアは技術的な図面をレンダリングします。ある特定の描画により、 OutOfMemoryExceptionが発生するたびにアプリケーションがクラッシュしました。調査したところ、異常なことは何もありませんでした。アプリは多くのメモリを要求せず、多くのハンドルを使用しませんでした。例外をキャッチしようとしましたが、アプリは別の例外をスローせずに描画を終了しました。実際、 OutOfMemoryExceptionは常に1つしかなく、それを引き起こしたのは常に同じグラフィックプリミティブでした。

次のコードは、この特定のクラッシュを引き起こすために最低限必要なものです。画像サイズ、ペンのスタイル、座標の正確な組み合わせが例外の原因になっているようです。座標を小数点以下3桁に切り捨てると、グラフィックスの寸法を小さくしたり、ダッシュせずにペンを使用したりするのと同様に、座標が消えます。

using (Bitmap b = new Bitmap(200, 200))
{
  using (Graphics g = Graphics.FromImage(b))
  {
    using (Pen p = new Pen(Color.Black))
    {
      p.DashPattern = new float[]{10.0f, 2.0f};

      RectangleF r = new RectangleF(
        BitConverter.ToSingle(new byte[]{0xD3, 0x56, 0xB3, 0x42}, 0),
        BitConverter.ToSingle(new byte[]{0x87, 0x2D, 0x17, 0x43}, 0),
        BitConverter.ToSingle(new byte[]{0xE2, 0x81, 0xD1, 0x3F}, 0),
        BitConverter.ToSingle(new byte[]{0xE2, 0x81, 0xD1, 0x3F}, 0));
      float st = BitConverter.ToSingle(new byte[]{0x6B, 0xF6, 0x1A, 0x42}, 0);
      float sw = BitConverter.ToSingle(new byte[]{0x6D, 0x33, 0x4F, 0x40}, 0);

      g.DrawArc(p, r, st, sw);
    }
  }
}

この場合、回避策を作成するのは複雑ではありませんが、誰かがこれについて説明しているかどうか疑問に思いました。

4

1 に答える 1

6

System.Drawingは、.NETのリリースよりも何年も前から存在するアンマネージライブラリであるGDI+のラッパーです。それはCapiの典型的な問題に悩まされており、エラー報告はかなり貧弱です。GDI +には20の異なるエラーコードしかありませんが、そのような大きなコードのチャンクにはあまりありません。それらも非常に不透明で、特定の問題はStatus::GenericErrorです。共通点がない可能性のある多くのエラー状態に対して返される、かなり一般的なエラー。

System.Drawingは、これらのエラーコードが設計上説明的ではなかったため、これらのエラーコードをより説明的にするためにほとんど何もできませんでした。Status::OutOfMemoryもそのパターンに適合します。それでできることはほとんどありませんが、同じことを意味する管理された例外を生成します。残念ながら、OutOfMemoryExceptionは.NETで非常に特殊であるため、これも適切な選択ではありませんでした。

勝つためのいくつかの方法でここにたくさんの損失。GDI +の不十分なエラー報告を額面どおりに受け取り、問題を修正する必要があります。この場合、非常に小さな円弧に破線のペンを使用しないようにすることで問題が解決する可能性が高くなります。とにかくダッシュパターンは見えません。

于 2013-02-18T15:19:12.183 に答える