본문 바로가기

Dev::DotNet/WinForm

Spread 에서 이미지 Attach 시 Memory Leak

Spread 의 Annotation 기능을 제공하는데 그 중에 이미지를 Attach 할 수 있는 기능이 있다.


[FarPoint.Win.Resouce Portal]



이미지를 Attach 하면 그 이미지에 대한 위치 / 크기 / 회전 에 대한 다양한 기능을 지원하는데..

문제는 여기서 발생한다. 


아래는 Spread 에서 기본 제공하는 Resouce Portal 에서 이미지를 Attach 했을 때 작업관리자에 표시된 정보이다. 



사용 중인 메모리는 135메가 이다.


이제 그 이미지를 선택해서 아래와 같이 좌우로 한 10번 쯤 이동시켰다.



그리고 작업관리자에 메모리 사용량을 보면 약 70메가 정도가 급 상승한 것을 볼 수 있다.




별 다른 작업없이 그냥 그냥 올라간 이미지를 잡고 움직이는 것 만으로 사용하는 메모리가 급격히 올라간다. 

당연히 몇번 더 움직이면 더 올라간다.


참으로 놀랍지 않을 수가 없다.

설마 Spread 를 만든 사람들이 이걸 정녕 몰랐단 말인가...ㅡㅡ;


대충 테스트해본 결과 이미지를 그리는 동안 불필요하게 Bitmap 객체를 계속 재생성하는 듯 하면 

그 재생성된 Bitmap 을 해제를 안 시키고 있는 것 같다.


어쩌든...이미지 Attach 기능을 사용할려면 저 메모리 누수를 해결해야만 하는데...

간단하게 저 이미지를 담을 Shape 를 상속받아서 이미지 그리는 부분을 직접 그려주면 된다.


internal class  ImageRectangleShape :

        FarPoint.Win.Spread.DrawingSpace.RectangleShape,

        System.IDisposable

    {

  private Image mPicture = null;

 

        public new Image Picture

        {

            get

            {

                return this.mPicture;

            }

            set

            {

                if (this.mPicture != null)

                    this.mPicture.Dispose();

                this.mPicture = null;

 

                this.mPicture = value;

            }

        }

 

        public ImageRectangleShape()

            : base()

        {

            this.CanRotate = false;

        }

 

        public ImageRectangleShape(FarPoint.Win.Spread.DrawingSpace.RectangleShape Rect)

            : base(Rect)

        {

            this.CanRotate = false;

 

            if (Rect.Picture != null)

                this.mPicture = Rect.Picture.Clone() as Image;

 

            if (Rect.Picture != null)

                Rect.Picture.Dispose();

            Rect.Picture = null;

 

            if (base.Picture != null)

                base.Picture.Dispose();

            base.Picture = null;

        }

 

        public void Dispose()

        {

            if (this.mPicture != null)

                this.mPicture.Dispose();

            this.mPicture = null;

        }

 

        protected override void PaintPicture(Graphics g, Rectangle rPict)

        {

            if (this.mPicture != null)

            {

                g.DrawImage(

                    this.mPicture,

                    rPict,

                    new Rectangle(0, 0, this.mPicture.Width, this.mPicture.Height),

                    GraphicsUnit.Pixel);

            }

            base.PaintPicture(g, rPict);

        }

    }


Spread 의 RectangleShape 를 상속받아서 PaintPicture 메소드를 override 하면 된는데

중요한 건 RectangleShape 에 이미지를 넣는 프로퍼티인 Picture 를 재정의하여 중간에서 그 이미지를 가로쳐서 

별도로 따로 보관하고 있어야 한다.

그 가로챈 이미지를 가지고 PaintPicture 메소드에서 직접 그려줘서 불필요한 bitmap 이 생성되는 것을 막는 것이다.


지금 위의 소스로는 회전까지는 되지 않기 때문에 회전이 필요한 분들은...잘 돌리시면 된다.