2

私は現在、連続して約 16000 通の電子メール (ニュースレター) を生成する必要があるバッチに取り組んでいます。

スパムであるかどうかにかかわらず、私の質問は、これらの電子メールをどのように生成するかについてです。

メッセージの一部のフィールドは、カスタム値 (日付、ユーザー名など) に置き換える必要があります。

締め切りとコードの再利用性の理由から、私のテンプレートは、正規表現で簡単に見つけられるいくつかの「_FIELDNAME」フィールドを含む HTML ファイルです。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
...
<body>
<p>Hi _NAME, _DATE newsletter.</p>
</body>
...

ファイルは約 1000 行なので、ロードすると非常に大きな文字列になります。

まず、HTML ファイル テンプレートを文字列で 1 回読み込みます。

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です。これは、私の置換機能によるものです(コメントしようとすると、メモリリークがなくなりました)。

16000回の反復でメモリをオーバーフローさせずに、テンプレート内の多くのフィールド (~50) を置き換えるにはどうすればよいですか? 正規表現(ただし文字列を使用)や一時ファイルを使用するなど、いくつか試してみましたが、どちらも満足できませんでした。

よろしくお願いします。

4

3 に答える 3

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
    );

実際には a を通過する必要はまったくありませんStringBuilderFile.ReadAllLines()トークンを含む行の値のみを交換すると、速度 (およびおそらくリソース使用量) が大幅に向上します。

UPDATEオーバーロードの使用を強制するために、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
于 2012-07-31T13:24:48.440 に答える
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;
  }
于 2012-07-31T13:34:07.933 に答える
0

多くの解決策を試した後、最終的にバッチを最初からやり直すことにしました。

適切な XSLT ファイルを使用して、XML 構成から HTML を生成するようになりました。

メモリ消費量は時間の経過とともに増加しますが、遅くなりました。私のコンピューターには6GBのRAMがあり、他に実行する巨大なプロセスがないため、ガベージコレクターは収集したくないと思います。

于 2012-08-01T13:37:37.747 に答える