我目前正在制作一个必须连续生成约16000封电子邮件的批次(简报)。
无论是垃圾邮件还是垃圾邮件,我的问题都是关于如何生成这些电子邮件。
邮件中的某些字段必须替换为自定义值(当天的日期,用户的名称等)。
对于某些截止日期和代码可重用性原因,我的模板是一个HTML文件,其中包含一些“_FIELDNAME”字段,可以通过正则表达式轻松识别:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
...
<body>
<p>Hi _NAME, _DATE newsletter.</p>
</body>
...
该文件约为1000行,因此在加载时它是一个非常大的字符串。
首先,我在字符串中加载一次HTML文件模板:
string template = File.ReadAllText(@"Template/newsletter.html");
替换功能如下所示:
return new StringBuilder(template)
.Replace("_DATE", profileConfig.SelectedMonth.ToString("MMMM yyyy"))
.Replace("_NAME", profileConfig.Name)
.ToString();
问题是每次迭代内存消耗略有增加。 1000次迭代大约50MB,这是由于我的替换功能(我试图评论它,内存泄漏消失了)。
如何在模板中替换多个字段(~50)而不会溢出内存以进行16000次迭代? 我试了几个东西,比如使用正则表达式(但它使用字符串)或临时文件,但两个都不满意我。
提前感谢您的帮助。
答案 0 :(得分:3)
如果您可以使用_DATE
,_NAME
等替换{0}
,{1}
等,则可以尝试string.Format()
模板将成为:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
...
<body>
<p>Hi {0}, {1} newsletter.</p>
</body>
...
代码看起来像这样:
return string.Format(template,
profileConfig.SelectedMonth.ToString("MMMM yyyy"),
profileConfig.Name
);
您实际上根本不需要经历StringBuilder
。如果你去了File.ReadAllLines()
并且只在包含标记的行中交换了值,那么你的速度(以及可能在资源使用方面)会大大受益。
更新为了强制使用string.Format(string format, params object[] args)
重载,您可能必须将所有参数放入集合中。
以下内容应该使这个解决方案适合您(我测试了多达1000个参数,并且它的工作和非常快)。
List<string> tokenValues = new List<string>
{
profileConfig.SelectedMonth.ToString("MMMM yyyy"),
profileConfig.Name,
<follow with your other values>
};
return string.Format(template, tokenValues.ToArray()); //.ToArray() is mandatory
答案 1 :(得分:1)
var patterns = new Dictionary<string, string>();
patterns["_Date"] = profileConfig.SelectedMonth.ToString("MMMM yyyy");
patterns["_Name"] = profileConfig.Name;
var builder = new StringBuilder(template.Length);
for (var i = 0; i < template.Length;)
{
var pattern = CompareAndFindPattern(template, i, patterns);
if (pattern != null)
{
builder.Append(pattern.Value.Value);
i += pattern.Value.Key.Length;
}
else
{
builder.Append(template[i]);
i++;
}
}
static KeyValuePair<string, string>? CompareAndFindPattern(string template, int index, Dictionary<string, string> patterns)
{
foreach (var pattern in patterns)
{
if (string.Compare(template, index, pattern.Key, 0, pattern.Key.Length) == 0)
return pattern;
}
return null;
}
答案 2 :(得分:0)
尝试了很多解决方案后,我终于决定从头开始重新启动我的批处理。
我现在使用适当的XSLT文件从XML配置生成HTML。
内存消耗量会随着时间的推移而增加但现在变慢了。我想垃圾收集器不想收集,因为我的计算机有6GB内存,没有其他大型进程可以运行。