Bitmap, pictureBox에 관한 질문 한가지더 드립니다

이번 질문은 메모리와 관련된 내용인데요…
이미지 캡쳐를 해서 계속해서 화면에 업데이트 하는 간단한 프로그래을 만든다고 했을때 인데요…
메모리가 계속올라가는 것이 좀 걸려서 using 문으로 다음과 같이 하려고 하는데요…
private Bitmap method1(Bitmap b)
using (var b = new Bitmap(xxx, xxx))
{
b에 대한 픽셀 처리
return b
}

위와같은 method1 을 호출했을때 using에 의해서 메모리가 해제되버리니 메서드 호출후에
pictureBox에 처리한 b를 넣으려하면 에러가 나 버리는데요…이럴때 메모리 문제도 해결하고
pictureBox에 이미지를 잘 넣어줄수 있는 방법이 있나요?

질문이 너무 이상한거 같기도 한데 제가 하려는걸 모두 설명드리기에 한계가 있다보니 요점만 문의드리는점
양해부탁드립니다.
초보자니까 드리는 질문이라 생각해 주시면 감사드리겠습니다.

좋아요 1

해제하는 메모리는 pictureBox에 대입하는 메모리가 아니어야 합니다. 기존 pictureBox가 보유했던 Bitmap 이미지를 해제하면 됩니다.

좋아요 1

using 문을 사용할 수 있는 것은 만들 객체가 IDisposable 유형인 경우에만 가능합니다.

질문을 봤을 때 이 IDisposable 인터페이스에 대해 이해가 없으신 것 같아 해당 내용으로 한 번 찾아보시면 좋을 것 같아요.
여기서 설명하기에는 너무 내용이 방대해서… 직접 찾아보는 것을 권장합니다. 한글 영문 상관없이요.

좋아요 1

제가 이해를 잘못해서 다시 한번 여쭙겠습니다.
예를 들어 아래와 같이 한다고 하면요…
public partial class Form1 : Form
{
Bitmap a = new Bitmap(pictureBox1.image);
pictureBox2.image = method1(a);

     private Bitmap method1(Bitmap b); {
     using  (var b = new Bitmap(xxx, xxx))
     {
     b에 대한 픽셀 처리
     return b
     }                                                            }

}
위 코드에서 pictureBox2에 이미지를 넣으려 할때 이미 method1에서 b가 해제되어 버려서
에러가 나는것 같은데요…이럴때 pictureBox2에 위에 예처럼 using문을 사용하면서 할수 있는 방법이
있나해서 여쭙네요~~

좋아요 1

위에 @level120 님이 말씀한 것 처럼 using 대상은 IDisposable 인터페이스를 구현한 무엇입니다.
이 인터페이스를 구현한 대상은 필요로 할 때 자원을 해제하는 기능을 제공하게 됩니다.
여기서는 Bitmap이 되고요.

picturebox에 픽셀처리된 Bitmap을 계속 설정하게 되면 메모리가 증가합니다. 이유는,
.NET은 메모리 해제를 가비지 컬렉터에 위임하기 때문인데요, 그 반증으로 C#으로 짠 코드는 할당된 개체를 해제하는 메커니즘이 없습니다.
그런데, 가비지 컬렉터에 의해서 메모리를 정리하는 것은 상황에 따라 문제가 있습니다. 가령, 해제가 되기 까지 그 자원을 쓸 수 없다던가, 메모리가 해제되기까지 상황은 메모리가 계속 증가하게 되기 때문에, 그 상황이 사용자 친화적이지 않을 수 있습니다. 이런 상황 때문에 IDisposable 인터페이스가 등장했고 C#에서는 using을 통해 즉각적으로 자원을 해제합니다. 그 해제 대상은 관리 자원(GC 대상) 수도 있고 비관리 메모리(GC 대상이 아님)일 수도 있고 둘 다 일수 있습니다. 그러나 지금은 너무 깊게 들어가지 맙시다.

  1. Bitmap을 할당하고 관련 픽셀처리를 한다.
  2. picturebox에 작업한 비트맵을 적용한다.
  3. 다시 1로 이동

이런 로직이라고 할 때 다음처럼 구현해야 합니다.

  1. Bitmap을 할당하고 관련 픽셀처리를 한다.
  2. picturebox에 기존 비트맵이 있다면 임시 변수에 복사한다.
  3. picturebox에 작업한 비트맵을 적용한다.
  4. 임시 복사한 비트맵을 해제 한다. (beforeBitmap이라고 가정했을 경우 beforeBitmap.Dispose())
  5. 다시 1로 이동
좋아요 1

아네…이왕 여쭙는거 하나만 더 여쭙겠습니다.
사실은 질문드리기 전에 아래와 같은 코드로 해봤는데요…우선 간단하게

Bitmap a = new Bitmap(pictureBox1.image); //픽처박스1에 있는 이미지 가져옴
…이미지 a를 가공하고요…
pictureBox2.image=a; 가공한 a를 픽처박스2 에 넣는다.
a.Dispose();

이렇게 해봤는데 에러나길래 이게 안되서 위에있는 처음질문 부터 다 시작된거라서요…
한번더 봐주시면 감사드리겠습니다.

좋아요 1

pictureBox2.imagea는 같은 곳을 참조합니다. 그러므로 a.Dispose()를 하면 안됩니다. 이런 코드가 아니라,

var beforeImage = pictureBox2.Image;
pictureBox2.Image = a;
beforeImage.Dispose();

하셔야 합니다.

좋아요 1

a를 계속 업데이트 해주는데 메모리가 계속 치고 올라가서 그러는건데요…물론 시간이 좀 지나면
GC가 해결해주는거 같긴한데 a를 그냥 이대로 놔둬도 상관없나 싶어서요~~

좋아요 1

첨부한 캡쳐 화면을 참고 해주세요.

제가 테스트 했을 때는 프로세스 메모리가 지속적으로 24 Mbytes 수준을 유지합니다.

Timer1_Tick() 메소드는 100ms (초당 10회)로 호출하도록 하였으며, 관련된 소스코드는 스크린샷된 화면에 모두 확인할 수 있습니다.

.NET 버젼에 따라 동작이 다를 수는 있겠습니다.

좋아요 1

아…네…감사합니다.
좀더 열공하고 다시 여쭐께요~~아직 지식이 짧아서 제 질문을 제대로 전달드리지 못하는거같고
직접코딩까지 해서 보여주시는데 자꾸 귀찮게 해드릴수 없어 이문제는 여기까지 도움받은것으로
정말정말 감사드리며 다음에 다시 여쭙도록 하겠습니다. 감사합니다.

좋아요 1