gpt4 book ai didi

c# - HttpRequest/HttpResponse内存泄漏? CF.NET 3.5 WIN CE 6.0

转载 作者:行者123 更新时间:2023-12-01 22:37:36 25 4
gpt4 key购买 nike

我已经尽一切努力使possito摆脱了我认为是Win CE 6.0设备上运行的CF.NET 3.5中的HttpRequest或HttpResponse类导致的内存泄漏。我正在使用它们与IP摄像机通信。

下面是我正在使用的当前代码。代码在线程上的自定义控件中运行,其优先级设置为低于正常,而backgroundworker设置为true。在我的一种表单上有两个控制对象。

我之所以说是当前的,是因为我尝试了以下代码的异步请求和其他排列,而没有减少内存消耗:

    protected void CamRefreshThread()
{
while (true)
{
if (false != CamEnabled)
{
HttpWebRequest HttpReq = null;

try
{
lock (LockObject)
{
// create request
HttpReq = (HttpWebRequest)WebRequest.Create("http://" + this.Ipv4Address + "/axis-cgi/jpg/image.cgi");
HttpReq.Timeout = 5000;
HttpReq.ReadWriteTimeout = 5000;
HttpReq.Credentials = new NetworkCredential(this.CamUserName, this.CamPassword);
}

/* indicate waiting for reponse */
ResponseRxed = false;
// get response
using (HttpWebResponse HttpResp = (HttpWebResponse)HttpReq.GetResponse())
{
// get response streamImageFromStream
using (Stream ImgStream = HttpResp.GetResponseStream())
{
// get bitmap
using (Bitmap ImgFrmStream = new Bitmap(ImgStream))
{
if (false != CamEnabled)
{
/* indicate response has not timed out */
ResponseTimedOut = false;
ResponseFirst = true;
// marshall bitmap
this.Invoke(GetBitmapDelegate, ImgFrmStream);
/* indicate response rxed */
ResponseRxed = true;
}
}
}
}
}
catch (WebException e)
{
if (false == ResponseTimedOut)
{
ResponseTimedOut = true;
ResponseFirst = false;
this.Invoke(RefreshDisplayDelegate);
}
}
catch (Exception)
{

}
finally
{
if (null != HttpReq)
{
HttpReq.Abort();
}
}
}

Thread.Sleep(1);
}
}


我已经使用RPM对它进行了概要分析,并且随着内存的增长,System.Net命名空间和System.Threading命名空间的一堆根对象也是如此,其中包括一堆我没有创建的线程和同步对象。

我已附加了第一个和最后一个堆快照的堆比较图像。

我已经确保在所有允许它的对象上使用“ using”并调用dispose。另外,我确保在完成后中止请求。我在其他示例中已经看到了这一点,应该释放连接资源等。

这是一个奇怪的部分,如果我没有连接摄像机,则仅在抛出超时WebException时才会发生泄漏。连接摄像机后,设备可以运行数天而不会增加内存。另外,RPM中托管字节数和字节总数都在增加,因此我认为这不是未处理的泄漏。最后,我试图尽快从照相机中获取图像。我开始怀疑我是否只是没有给GC时间收集。但是,当发生收集时(我看到收集计数以RPM递增),托管字节数不会减少,而是保持增长。希望我做的事情很愚蠢,这很容易解决。一如既往,任何帮助或建议,我们感激不尽。

附加信息:

如果可能有助于了解,则从照相机线程调用的两个委托如下:

GetBitmapDelegate = new VoidDelegateBitmap(UpdateCamImage);
RefreshDisplayDelegate = new VoidDelegateVoid(RefreshCamImage);

protected void UpdateCamImage(Bitmap Frame)
{
if (null != BmpOffscreen)
{
BmpOffscreen.Dispose();
}

BmpOffscreen = (Bitmap)Frame.Clone();
Refresh();
}

protected void RefreshCamImage()
{
Refresh();
}


附加信息2:

为了完成此信息,我在下面添加了OnPaint()等。我曾将位图绘制到摄像机的屏幕上:

protected override void OnPaint(PaintEventArgs e)
{
string DisplayString = null;

if (false == CamEnabled)
{
DisplayString = string.Empty;
}
else if (false != ResponseTimedOut)
{
DisplayString = "Communication Timeout!";
}
else if ((null != BmpOffscreen) && (false != ResponseFirst))
{
e.Graphics.DrawImage(BmpOffscreen, 0, 0);
}
else
{
DisplayString = "Loading...";
}

if (null != DisplayString)
{
e.Graphics.Clear(this.BackColor);

using (SolidBrush StringBrush = new SolidBrush(this.ForeColor))
{
using (StringFormat Format = new StringFormat())
{
Format.LineAlignment = StringAlignment.Center;
Format.Alignment = StringAlignment.Center;
e.Graphics.DrawString(DisplayString, this.Font, StringBrush, this.ClientRectangle, Format);
}
}
}
}

protected override void OnPaintBackground(PaintEventArgs e)
{

}


更新:

这是我不明白的。由于HttpRequest只是一个保存信息的对象,并且无法关闭/处理,并且由于抛出WebException超时而HttpResponse仍然为null(无法关闭),因此引用用于尝试该请求的资源是什么?唯一的解释是HttpRequest对象拥有一些引用,该引用在调用Abort时应释放用于发出请求的资源,而我看到的这些资源在RPM中没有恢复。由于我调用Abort(),并且由于HttpRequest对象仅在请求期间处于作用域内,因此我看不到如何无法收集任何引用的资源。

更新2:

好吧,我让它在启用摄像头的情况下运行并允许超时继续,然后我禁用了摄像头,消除了HttpRequest尝试和超时,并让它在一天的剩余时间内运行。归根结底,GC停留在相同的值(根据过去的测试,它应该增长了约6MB),证明这与给GC收集时间无关,至少在我看来。因此,资源仍然处于混乱状态,我需要弄清楚到底是什么使它们扎根。希望我能明白
并给出另一个更新。直到那时...

边注:

是否有人在使用CF.NET 3.5的WIN CE设备上使用HttpRequest / HttpResponse从IP摄像机获取图像?如果是这样,是否有一个测试案例来确定在不确定的时间内相机丢失通讯?那应该是我问的第一件事,因为我还没有找到很多示例来说明如何从嵌入式设备与IP摄像机通信。

更新3:

好吧,我认为我偶然发现了针对我特定问题的修复程序。关于默认连接数和最大空闲时间,我对ServicePointManager静态类成员进行了一些更改:

ServicePointManager.DefaultConnectionLimit = 4;
ServicePointManager.MaxServicePointIdleTime = 1000;


由于我随时最多可以连接4个摄像头,并且由于HttpRequest的超时设置为5000ms,因此我认为我将尝试最大1000ms的空闲时间来查看会发生什么情况。我让两个装置在没有连接相机的情况下通宵运行(每5000毫秒定时)。通常会发生的是我早上来了,设备将坐在那里,并收到一条OOM消息,并且GC内存和物理内存将为我的系统最大化。嗯,这两个设备的存储级别与我昨晚离开时的存储级别相同。因此,我希望这是解决我的问题的方法。基于MSDN文档:


ConnectionLimit属性设置ServicePoint可以与Internet资源建立的最大连接数。创建ServicePoint时,ConnectionLimit属性的值设置为ServicePointManager.DefaultConnectionLimit属性的值。随后对DefaultConnectionLimit的更改对现有ServicePoint实例无效。

MaxIdleTime属性包含以毫秒为单位的时间长度,允许ServicePoint保留与Internet资源的空闲连接,然后再将其回收再用于其他连接。您可以将MaxIdleTime设置为Timeout.Infinite,以指示ServicePoint永不超时。创建ServicePoint时,MaxIdleTime属性的默认值为ServicePointManager.MaxServicePointIdleTime属性的值。对MaxServicePointIdleTime属性的后续更改对现有ServicePoint实例无效。

MaxServicePointIdleTime属性设置创建ServicePoint实例时ServicePointManager分配给MaxIdleTime属性的最大空闲时间。对该值所做的更改将仅影响在更改该值之后初始化的ServicePoint实例。 ServicePoint闲置了MaxIdleTime中指定的时间后,就可以进行垃圾回收。当与ServicePoint关联的连接列表为空时,ServicePoint处于空闲状态。


对我而言,所有这些的关键是明确指出,在服务点处于最大空闲时间后处于空闲状态之后,就可以进行垃圾收集了。我已经看到100到900秒之间的任何时间作为此值的默认值,具体取决于描述所涉及的框架版本。在我认为这是修复程序之前,我将做更多测试。我想从任何玩过这些属性的人那里解决他们的特定问题,以及这是否是我所看到的问题的根本原因是否有意义。

最佳答案

只需将您的AllowWriteStreamBuffering对象的HttpWebRequest属性设置为false:

HttpReq.AllowWriteStreamBuffering = false;
HttpReq.AllowAutoRedirect = false;

关于c# - HttpRequest/HttpResponse内存泄漏? CF.NET 3.5 WIN CE 6.0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7114970/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com