我有一个继承的.NET 4.0应用程序作为Windows服务运行.我不是任何一个.NET专家,但在编写代码30多年后,我知道如何找到自己的方式.
当服务首次启动时,它会在大约70MB的私人工作集上进行计时.服务运行的时间越长,所需的内存就越多.这种增加并不是那么引人注目,只是坐着观看,但我们已经看到在应用程序运行了很长时间(100天以上)之后的情况,它达到了多GB(当前记录为5GB).我将ANTS Memory Profiler附加到正在运行的实例上,发现ExpandoObject的使用似乎占用了几兆字节的字符串,这些字符串不会被GC清理掉.可能还有其他泄漏,但这是最明显的,所以它首先受到攻击.
我从其他SO帖子中了解到,当读取(但不是写入)动态分配的属性时,ExpandoObject的"正常"使用会生成内部RuntimeBinderException.
dynamic foo = new ExpandoObject();
var s;
foo.NewProp = "bar"; // no exception
s = foo.NewProp; // RuntimeBinderException, but handled by .NET, s now == "bar"
Run Code Online (Sandbox Code Playgroud)
你可以在VisualStudio中看到异常,但最终它是在.NET内部处理的,你得到的就是你想要的值.
除了...异常的Message属性中的字符串似乎保留在堆上,并且永远不会收到Garbage Collected,即使在生成它的ExpandoObject超出范围之后很久.
简单的例子:
using System;
using System.Dynamic;
namespace ConsoleApplication2
{
class Program
{
public static string foocall()
{
string str = "", str2 = "", str3 = "";
object bar = new ExpandoObject();
dynamic foo = bar;
foo.SomePropName = "a test value";
// each of the following …Run Code Online (Sandbox Code Playgroud)