我的应用 巨大的内存泄漏 ,内存使用率在运行1天后 40MB到700MB 。我用C#编码,我不知道如何阻止泄漏。我怀疑下面2个功能是罪魁祸首。
SendLiveVideo :它从相机捕获并通过套接字发送 ResizeImage :为了节省带宽,它会在我通过套接字发送之前调整图像大小。
我的应用程序调用第三方库( LibImage,Libcapture)从旧网络摄像头(4个摄像头)捕获图像,并作为视频流传输到LAN连接客户端列表。
我已经在退出Sendvideo函数时在finally语句中为我的*变量分配了 null 值以释放内存,但它似乎无法正常工作。
我是否需要使用Dispose方法?
this.timer_stream0.Interval = 30; /*I capture image and send to client this every 30 milseconds make it as video stream to human eye*/
this.timer_stream0.Tick += new System.EventHandler(this.timer_stream0_Tick);
private void timer_stream0_Tick(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(SendLiveVideo, 0);
ThreadPool.QueueUserWorkItem(SendLiveVideo, 1);
ThreadPool.QueueUserWorkItem(SendLiveVideo, 2);
ThreadPool.QueueUserWorkItem(SendLiveVideo, 3);
}
void SendLiveVideo(object state)
{
LibImage image=new LibImage();
LibCapture capture_camera=new LibCapture();
int cam = (int)state;
System.Collections.ArrayList m_workerSocketList_Video =
ArrayList.Synchronized(new System.Collections.ArrayList());
switch (cam)
{
case 0:
{
image = image0;
capture_camera = capture_camera0;
m_workerSocketList_Video = m_workerSocketList_Video0;
break;
}
case 1:
{
image = image1;
capture_camera = capture_camera1;
m_workerSocketList_Video = m_workerSocketList_Video1;
break;
}
case 2:
{
image = image2;
capture_camera = capture_camera2;
m_workerSocketList_Video = m_workerSocketList_Video2;
break;
}
default:
{
image = image3;
capture_camera = capture_camera3;
m_workerSocketList_Video = m_workerSocketList_Video3;
break;
}
}
byte[] imageData=new byte[1000 * 1000 * 10];
try
{
try
{
capture_camera.Capture(image);
}
catch
{
// objData = null;
imageData = null;
return;
}
imageData = image.SaveToMem(PNG);
var stream = new MemoryStream(imageData);
{
var bitmap = new Bitmap(stream);
bitmap = ResizeImage(bitmap, new Size(150, 112));
//stream = null;
MemoryStream streamnew = new MemoryStream();
bitmap.Save(streamnew, ImageFormat.Png);
imageData = streamnew.ToArray();
bitmap = null;
streamnew = null;
}
Socket workerSocket = null;
for (int i = 0; i < m_workerSocketList_Video.Count; i++)
{
workerSocket = (Socket)m_workerSocketList_Video[i];
if (workerSocket != null)
{
if (SocketConnected(workerSocket))
{
workerSocket.Send(imageData);
}
}
}
}
catch (SocketException se)
{
// MessageBox.Show(se.Message);
return;
}
finally
{
image = null;
capture_camera = null;
imageData = null;
m_workerSocketList_Video = null;
}
}
private Bitmap ResizeImage(Bitmap imgToResize, Size size)
{
try
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)size.Width / (float)sourceWidth);
nPercentH = ((float)size.Height / (float)sourceHeight);
if (nPercentH < nPercentW)
nPercent = nPercentH;
else
nPercent = nPercentW;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap b = new Bitmap(destWidth, destHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
b.SetResolution(200, 200);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighSpeed;
g.SmoothingMode = SmoothingMode.HighSpeed;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return b;
}
答案 0 :(得分:1)
试着看看我的回答here。
基本上,这是一种如何找到泄漏原点的方法 这实际上是一个复制粘贴:
请注意,此方法的缺点是:
答案 1 :(得分:0)
我会用
using(Graphics g = Graphics.FromImage((Image)b))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighSpeed;
g.SmoothingMode = SmoothingMode.HighSpeed;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
}
return b;
实现IDisposable的每种类型的模式,这样你就不会忘记处理任何东西了吗?
答案 2 :(得分:0)
每当使用IDisposable实例时,您都必须使用using关键字。
使用(MemoryStream streamnew = new MemoryStream()) //你的位图实例也一样!
如果是这种情况,你必须检查LibImage和LibCapture的实现以及它们包装的本机库。
没有必要实例化所有这三个变量image,capture_camera和m_workerSocketList_Video,因为你要在switch语句中初始化它们,除非。如果这些类是库的本机包装器,那么这将导致显着的内存丢失,这些库很难管理它们使用的内存。
使用这行代码,
imageData = image.SaveToMem(PNG);
如果SaveToMem函数返回正确的缓冲区,则不需要启动imageData数组!