C#4.5的新特性,异步处理,同步的编码方式,大大的提高了编程效率。但是今天却由于异步的使用,导致了一个非常严重的内存泄漏。
崩溃截图:
由于本程序是用纯C#开发,不存在非托管内存,而且没有使用静态变量,为什么还是会有内存泄漏了。迷茫了一个上午。
快到中午的时候,一个偶然的机会,执行了异常清理,就是把异步等待进行超时处理之后,内存立马降下来了。
很快定位原因出在await一直没有得到应答上面。
通过研究发现,在调用await之后,系统会把await之前的函数变量都保存起来,等待应答到来之后,在恢复过来,然后好接下来处理。问题就出来这些函数变量上面。我有一个类需要保存起来,在应答回来之后使用。
var MediaRsp = await ryMedia.GetTcpAcceptAsync(sdp_Request.parameters.sessionId).ConfigureAwait(false);
if(MediaRsp.Result == RyResult.Success)
{
RailwaySend railwaySend = new RailwaySend()
{
Media = MediaRsp.media,
SendType = SendType.RailWay,
};
session.AddSend(sdp_Request.parameters.sessionId, railwaySend);
}
session类在另外一个线程一直在执行发送视频流的操作。
public void SendMedia(byte[] buffer)
{
byte[] bSend = new byte[buffer.Length];
Array.Copy(buffer, bSend, buffer.Length);
}
理论上讲,new的数据,是托管内存,应该会被Gcc回收,但是实际上没有。
结论:
await之前的涉及到的类,在await到达之前,所产生的托管内存都不会被Gcc回收。这就是导致最终内存泄漏的原因。