[英]Memory leaks with C# app? How to stop?
My app has huge memory leak and memory usage spiked from 40MB to 700MB after 1 day running . 我的应用程序运行1天后, 内存泄漏巨大 ,内存使用量从40MB激增至700MB 。 I'm coding with C# and I don't know how to stop leak.
我正在用C#编写代码,但我不知道如何阻止泄漏。 I suspect below 2 functions are main culprit.
我怀疑以下两个功能是主要的罪魁祸首。
SendLiveVideo : It captures from camera and send via socket. SendLiveVideo :它从摄像机捕获并通过套接字发送。
ResizeImage : In order to save bandwidth it resizes image before I send out via socket. ResizeImage :为了节省带宽,它会在我通过套接字发送之前重新调整图像的大小。
My app calls 3-rd party library( LibImage, Libcapture) capture image from old webcams (4 cameras) and stream as video to list of LAN connected clients. 我的应用程序调用第3方库( LibImage,Libcapture)从旧的网络摄像头(4个摄像头)捕获图像并将其作为视频流传输到LAN连接的客户端列表。
I already assigned null values to my *variables within finally statement upon exit of Sendvideo function in order to release memory, but it seems not working. 我已经在Sendvideo函数退出时为final语句中的*变量分配了空值,以释放内存,但似乎不起作用。
Do I need to use Dispose method instead? 我需要改用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;
}
Try taking a look at my SO answer here . 尝试在这里看看我的答案。
Basically, it is an approach of how to find the origin of the leak. 基本上,这是一种如何找到泄漏源的方法。
This is practically a copy-paste: 这实际上是一个复制粘贴:
Please note that the down sides of this method are: 请注意,此方法的缺点是:
I would use the 我会用
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;
pattern on each type which implements the IDisposable, this way you can't forget to dispose anything? 每个实现IDisposable的类型上的模式,这样您就不会忘记处理任何事情?
you have to use the using keyword whenever an IDisposable instance is used. 每当使用IDisposable实例时,都必须使用using关键字。
using (MemoryStream streamnew = new MemoryStream()) // The same goes for your bitmap instance ! using(MemoryStream streamnew = new MemoryStream())//位图实例也是如此!
you have to check on LibImage and LibCapture's implementations and the native libraries they're wrapping if it's the case. 如果是这种情况,则必须检查LibImage和LibCapture的实现以及它们要包装的本机库。
there is no need to instantiate all those three variables image, capture_camera and m_workerSocketList_Video since you're initializing them in your switch statement unless. 除非您在switch语句中初始化它们,否则无需实例化这三个变量image,capture_camera和m_workerSocketList_Video。 This will lead to significant memory loss if the classes are native wrappers around libraries that poorly manage the memory they use.
如果这些类是库的本机包装,将无法很好地管理它们使用的内存,这将导致大量内存丢失。
With this line of code, 有了这行代码,
imageData = image.SaveToMem(PNG); imageData = image.SaveToMem(PNG);
you don't need to initiate the imageData array if the SaveToMem function returns the right buffer ! 如果SaveToMem函数返回正确的缓冲区,则无需初始化imageData数组!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.