-1

誰かがタイマーを使用して実行時にいくつかのコードを実行するのを手伝ってくれましたが、しばらくすると、メモリを使用しているだけで解放されていないことがわかりました。

AppDomain について何か聞いたことがありますが、どこで使用するかわかりませんでした。

AppDomain は、そのメモリ リークに役立ちますか? 他に何か役立つことはありますか?

PS: GC.Collect() は役に立ちません。問題は、いくつかのテストを行ったので、問題の実行中にメモリを監視しているため、スクリプターを無効にすると(基本的に)同じ量を保持し、いくつかのコードでタイマーを開始して実行すると保持されることだと確信しています増加し、数分後に500k以上のメモリが使用される可能性があるため、そうです、メモリを使用しているだけのCSharpCodeProviderに問題があると確信しています。

これが私の実際のコードです。誰かがこの問題を解決してくれると助かります。

//It is executed in a timer of 500 ms
private void Run()
{
    foreach (Code ph in codeList)
    {
        Code p = ph;

        new Thread(delegate()
        {
            if (Monitor.TryEnter(p))
            {
                Scripter script = new Scripter();
                script.Compile(p.Code);
                Monitor.Exit(p);
            }
        }) { IsBackground = true }.Start();
    }
}

//That's my compile code
public bool Compile(string script)
{
    CSharpCodeProvider codeprovider = new CSharpCodeProvider();
    ICodeCompiler icc = codeprovider.CreateCompiler();
    CompilerParameters cp = new CompilerParameters();

    cp.ReferencedAssemblies.Add("System.dll");
    cp.ReferencedAssemblies.Add(System.Reflection.Assembly.GetExecutingAssembly().Location);

    cp.TreatWarningsAsErrors = false;

    cp.MainClass = "CodesRun";
    cp.CompilerOptions = "/target:library /optimize";
    cp.GenerateExecutable = false;
    cp.GenerateInMemory = false; //it was true, but same problem

    TempFileCollection tfc = new TempFileCollection(Application.StartupPath, false);
    CompilerResults cr = new CompilerResults(tfc);

    cr = icc.CompileAssemblyFromSource(cp, script);

    if (cr.Errors.Count > 0)
    {
        //Error
    }
    else
    {
        Assembly assembly = cr.CompiledAssembly;
        IScript teste = (IScript)assembly.CreateInstance("CodesRun.Script");
        teste.Run();
    }
    tfc.Delete();
    codeprovider.Dispose();

    return true;
}
4

1 に答える 1

0

using ディレクティブを使用して、オブジェクトを使い終わったらすぐに破棄してみてください。例えば:

using( Scripter script = new Scripter() ){
   script.Compile(p.Code);
   Monitor.Exit(p);
}

これでリークが修正されるわけではありませんが、メモリ フットプリントが少し減少するはずです (つまり、メモリができるだけ早く再利用されるはずです)。

@Andrew Barber が言ったように、メモリ プロファイリング ツールを使用してリークの存在を確認する必要があります。AQTime を使用していますが、有料です (ただし、それほど高価ではありません)。無料オプションについては、こちらで説明しています。

于 2012-04-09T19:00:52.033 に答える