none
compileassemblyfromsource 記憶體滿如何釋放 RRS feed

  • 問題

  • 前輩們好

    小弟有一個問題

    我呼叫這個程序來做一些運算值

    但是 跑一天後他會出現錯誤 導致整個城市崩潰

    請問我應該怎麼釋放他的記憶體呢

    感恩

    PS:  

      GC.Collect(); 是我後來加上 還不知道有沒有效果

    錯誤訊息如下

    2020/1/7 上午 07:40:43 CompilerCode 已發生類型 'System.OutOfMemoryException' 的例外狀況。
    2020/1/7 上午 07:40:44 CompilerCode 已發生類型 'System.OutOfMemoryException' 的例外狀況。
    2020/1/7 下午 10:56:20 CompilerCode 已發生類型 'System.OutOfMemoryException' 的例外狀況。
    2020/1/7 下午 10:56:21 CompilerCode 已發生類型 'System.OutOfMemoryException' 的例外狀況。
    2020/1/7 下午 10:56:22 CompilerCode 已發生類型 'System.OutOfMemoryException' 的例外狀況。
    2020/1/7 下午 10:56:24 CompilerCode 已發生類型 'System.OutOfMemoryException' 的例外狀況。
    2020/1/7 下午 10:56:25 CompilerCode 已發生類型 'System.OutOfMemoryException' 的例外狀況。
    2020/1/7 下午 10:56:26 CompilerCode 已發生類型 'System.OutOfMemoryException' 的例外狀況。
    2020/1/7 下午 10:56:27 CompilerCode 已發生類型 'System.OutOfMemoryException' 的例外狀況。
    2020/1/7 下午 10:56:29 CompilerCode 已發生類型 'System.OutOfMemoryException' 的例外狀況。
    2020/1/7 下午 10:56:30 CompilerCode 已發生類型 'System.OutOfMemoryException' 的例外狀況。
    2020/1/7 下午 10:56:31 CompilerCode 已發生類型 'System.OutOfMemoryException' 的例外狀況。
    2020/1/7 下午 10:56:31 CompilerCode 已發生類型 'System.OutOfMemoryException' 的例外狀況。
    2020/1/8 下午 02:41:00 CompilerCode 集合中已經存在檔名 'C:\Users\Administrator\AppData\Local\Temp\1\nqe0frt4\nqe0frt4.0.cs'。
    參數名稱: fileName
    2020/1/8 下午 02:41:00 CompilerCode 檔案 'C:\Users\Administrator\AppData\Local\Temp\1\nqe0frt4\nqe0frt4.out' 已經存在。
    2020/1/8 下午 02:41:04 CompilerCode 集合中已經存在檔名 'C:\Users\Administrator\AppData\Local\Temp\1\nqe0frt4\nqe0frt4.0.cs'。
    參數名稱: fileName
    2020/1/8 下午 02:41:04 CompilerCode 檔案 'C:\Users\Administrator\AppData\Local\Temp\1\nqe0frt4\nqe0frt4.out' 已經存在。
    2020/1/8 下午 02:41:09 CompilerCode 集合中已經存在檔名 'C:\Users\Administrator\AppData\Local\Temp\1\nqe0frt4\nqe0frt4.0.cs'。
    參數名稱: fileName
    2020/1/8 下午 02:41:09 CompilerCode 檔案 'C:\Users\Administrator\AppData\Local\Temp\1\nqe0frt4\nqe0frt4.out' 已經存在。
    2020/1/8 下午 02:41:23 CompilerCode 集合中已經存在檔名 'C:\Users\Administrator\AppData\Local\Temp\1\nqe0frt4\nqe0frt4.0.cs'。
    參數名稱: fileName
    2020/1/8 下午 02:41:24 CompilerCode 檔案 'C:\Users\Administrator\AppData\Local\Temp\1\nqe0frt4\nqe0frt4.out' 已經存在。
    2020/1/8 下午 02:41:27 CompilerCode 集合中已經存在檔名 'C:\Users\Administrator\AppData\Local\Temp\1\nqe0frt4\nqe0frt4.0.cs'。
    參數名稱: fileName
    2020/1/8 下午 02:41:28 CompilerCode 檔案 'C:\Users\Administrator\AppData\Local\Temp\1\nqe0frt4\nqe0frt4.out' 已經存在。

      private string CompilerCode(string Calculation)
            {
                string Anser = "0";
    
    
                CompilerResults cr;
    
                try
                {
                    // 4.CompilerResults
                    cr = objICodeCompiler.CompileAssemblyFromSource(objCompilerParameters, GenerateCode(Calculation));
    
                    if (cr.Errors.HasErrors)
                    {
                        //Console.WriteLine("編譯錯誤:");
                        foreach (CompilerError err in cr.Errors)
                        {
                            //Console.WriteLine(err.ErrorText);
                            Anser = err.ErrorText;
                        }
                    }
                    else
                    {
                        // 通过反射,调用HelloWorld的实例
                        Assembly objAssembly = cr.CompiledAssembly;
                        objCalculation = objAssembly.CreateInstance("DynamicCodeGenerate.Calculation");
                        objMI = objCalculation.GetType().GetMethod("OutPut");
    
                        Anser = objMI.Invoke(objCalculation, null).ToString();
    
                        objAssembly = null;
                    }
                }
                catch (Exception ex)
                {
                    Anser = "0";
                    MyExtenstions.Log("CompilerCode " + ex.Message);
                }
    
                cr = null;
    
                try
                {
                    // Put some objects in memory.
                    //MyGCCollectClass.MakeSomeGarbage();
                    //Console.WriteLine("Memory used before collection:       {0:N0}",
                    //                  GC.GetTotalMemory(false));
    
                    // Collect all generations of memory.
                    GC.Collect();
                    //Console.WriteLine("Memory used after full collection:   {0:N0}",
                    //                 GC.GetTotalMemory(true));
                }
                catch (Exception ex2)
                {
    
                }
    
                return Anser;
            }
     static string GenerateCode(string Calculation)
            {
                try
                {
                    StringBuilder sb = new StringBuilder();
                    sb.Append("using System;");
                    sb.Append(Environment.NewLine);
                    sb.Append("namespace DynamicCodeGenerate");
                    sb.Append(Environment.NewLine);
                    sb.Append("{");
                    sb.Append(Environment.NewLine);
                    sb.Append("    public class Calculation");
                    sb.Append(Environment.NewLine);
                    sb.Append("    {");
                    sb.Append(Environment.NewLine);
                    sb.Append("        public string OutPut()");
                    sb.Append(Environment.NewLine);
                    sb.Append("        {");
                    sb.Append(Environment.NewLine);
                    sb.Append("             return (" + Calculation + ").ToString(); ");//      sb.Append("             return \"Hello world!\";");
                    sb.Append(Environment.NewLine);
                    sb.Append("        }");
                    sb.Append(Environment.NewLine);
                    sb.Append("    }");
                    sb.Append(Environment.NewLine);
                    sb.Append("}");
    
                    string code = sb.ToString();
                    //Console.WriteLine(code);
                    //Console.WriteLine();
    
                    sb.Clear();
                    sb = null;
    
                    return code;
                }
                catch (Exception ex)
                {
                    MyExtenstions.Log("GenerateCode " + ex.Message);
                }
    
                return "";
            }



    • 已編輯 Luoco 2020年1月9日 上午 08:34
    2020年1月9日 上午 08:33

解答

  • 通常就是 Expression tree + interpreter

    Writing a Simple Math Expression Engine in C#


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/

    • 已標示為解答 Luoco 2020年1月12日 上午 03:12
    2020年1月10日 下午 03:23
    版主
  • 這邊有一個 VBNet 模仿 Script Control 的動態編譯可以參考:

    http://www.tlcheng.tk/TLCheng/Net/NetList.aspx?Action=Module&Module=36


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    • 已標示為解答 Luoco 2020年1月12日 上午 03:12
    2020年1月10日 下午 04:25

所有回覆

  • 看看這篇:

    https://tlcheng.wordpress.com/2013/09/28/vbnet-webbrowser-control-%E5%A3%93%E6%8A%91%E8%A8%98%E6%86%B6%E9%AB%94%E8%86%A8%E8%84%B9/


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2020年1月9日 下午 03:08
  •  

    應該是因為不斷地加入組件 (Assembly) 導致記憶體不足,如果你是 .NET Core 3.0 可以透過 AssemblyLoadContext.Unload 卸載組件;如果是 .NET Framework 需要用另外一種作法,就是在另一個 AppDomain 載入 Assembly,執行完後卸載 AppDoamin。

    參考:

    AppDomain.CreateDomain 方法

    AppDomain.CreateInstanceAndUnwrap 方法

    AppDomain.Unload(AppDomain) 方法


    不過,有考慮過需求上也許不需要靠這種方式來做?你的需求也許靠 Expression tree 就可以解決了,運算式樹狀架構 (C#)


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/


    2020年1月10日 上午 10:02
    版主
  • 感謝大哥幫忙

    我有先放一版上去試試看唷

    2020年1月10日 上午 10:15
  • 嗨嗨 

    大哥真是厲害 真的是這樣

    其實我最主要的功能是需要做

    讓用戶可以自行輸入  1+1 算出結果

    但是我只想的到這個方式

    還是有其他的方式不用走這方法呢

    感恩

    2020年1月10日 上午 10:34
  • 嗨嗨 

    大哥真是厲害 真的是這樣

    其實我最主要的功能是需要做

    讓用戶可以自行輸入  1+1 算出結果

    但是我只想的到這個方式

    還是有其他的方式不用走這方法呢

    感恩

    如果你的運算子很簡單,只有 +-*/,而且只有兩個運算元,那還有更簡單的做法,但如果會出現 1+2*3 -4/2 這種比較長的運算式,是可以用 Expression tree,只是寫起來有點費力。

    組建運算式樹狀架構


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/

    2020年1月10日 上午 11:03
    版主
  • 哇 我從來不知道有這個可以用

    太贊了

    那超過 兩個運算子  除了自組編譯 沒有比較好的方式嗎?

    2020年1月10日 下午 01:52
  • 通常就是 Expression tree + interpreter

    Writing a Simple Math Expression Engine in C#


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/

    • 已標示為解答 Luoco 2020年1月12日 上午 03:12
    2020年1月10日 下午 03:23
    版主
  • 動態編譯時比較花時間,所以若是程式碼開啟後沒有變更函數的話,編譯一次載入記憶體即可。

    若是經常性的變動,建議可以編譯成 32 bits 程式,呼叫 windows 內建的 Script Control ,Script Control 使用內建直譯引擎,支援 javascript / vbscript 組成的函數。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2020年1月10日 下午 04:23
  • 這邊有一個 VBNet 模仿 Script Control 的動態編譯可以參考:

    http://www.tlcheng.tk/TLCheng/Net/NetList.aspx?Action=Module&Module=36


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    • 已標示為解答 Luoco 2020年1月12日 上午 03:12
    2020年1月10日 下午 04:25
  • 哇 讚喔

    小弟來試試看 感謝前輩指導

    2020年1月12日 上午 03:14