0

だから私の問題は、いくつかのサイトからhtmlページを取得し、変更後にWebブラウザーに表示する個人用のアプリを1つ作成したことです。すべてが正常に機能していますが、私を混乱させたのは、それが取っているメモリです. 3 ~ 4 語のクエリを実行すると、メモリ使用量は約 300 ~ 400 MB に達します。

アプリからのいくつかの関連コードは

void sentenceBox_Navigated(object sender, WebBrowserNavigatedEventArgs e)
        {
            GC.Collect();
        }
    HtmlDocument hd;
    Word w=new Word();

    private void button1_Click(object sender, EventArgs e)
    {
        button1.Enabled = false;
        status.Text = "Processing english req..";
        if (checkInHis(queryTxt.Text))
        {
            sentenceBox.AllowNavigation = true;
            richTextBox1.Text = w.engDefinition;
            sentenceBox.DocumentText = w.engDefinition;
            status.Text = "Word found in History.DONE!";
            button1.Enabled = true;
            return;
        }
        if (w == null || w.engWordProp != queryTxt.Text)
        {
            w.engWordProp=queryTxt.Text;
            w.loadEngDefn();
            w.engDefnLoadedEvent += new Word.engDefnLoaded(w_engDefnLoadedEvent);
            return;
        }
        w.loadEngDefn();
        w.engDefnLoadedEvent += new Word.engDefnLoaded(w_engDefnLoadedEvent);
    }

    void w_engDefnLoadedEvent(Word sender, EventArgs data)
    {
        sentenceBox.AllowNavigation = true;
        sentenceBox.DocumentText = sender.engDefinition;
        sender.engDefnLoadedEvent -= w_engDefnLoadedEvent;
        button1.Enabled = true;
    }

    private void addToHistory(Word w)
    {
        status.Text = "Saving offline...";
        if (!checkInHis(w.engWordProp))
        {
        history.Add(w);
//        label1.Text = w.engWordProp + " saved in localdb. Database size: " + history.Count;

        w = null;
        }
        else
        {
//                label1.Text = w.engWordProp + " Skipped. Database size: " + history.Count;

        }
    }

    private Boolean checkInHis(string p)
    {
        status.Text = "checking offline storage...";
        foreach (Word item in history)
        {
            if (item.engWordProp == p)
            {
                status.Text = "Word found in history.";
                w = item;
                return true;
            }
        }
        status.Text = "Not found in offline database...";
        return false;
    }

    private void sentenceBox_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        ((WebBrowser)sender).AllowNavigation = false;
    }

    private void button2_Click_1(object sender, EventArgs e)
    {
        button2.Enabled = false;
        status.Text = "Requesting hindi definition...";
        if (checkInHis(queryTxt.Text))
        {
            sentenceBox.AllowNavigation = true;
            sentenceBox.DocumentText = w.hindiDef;
            status.Text = "DONE!";
            button2.Enabled = true;
            return;
        }
        if (w == null || w.engWordProp != queryTxt.Text)
        {
            w.engWordProp=queryTxt.Text;
            w.loadHinDefn();
            w.HindiDefLoadedEvent += new Word.hindiDefLoaded(w_HindiDefLoadedEvent);
            return;
        }
        w.loadHinDefn();
        w.HindiDefLoadedEvent += new Word.hindiDefLoaded(w_HindiDefLoadedEvent);
    }

    void w_HindiDefLoadedEvent(Word sender, EventArgs data)
    {
        sentenceBox.AllowNavigation = true;
        sentenceBox.DocumentText = sender.hindiDef;
        button2.Enabled = true;
        sender.HindiDefLoadedEvent -= w_HindiDefLoadedEvent;
    }

 private void button3_Click(object sender, EventArgs e)
    {
        button3.Enabled = false;
        saveWord(w);
        button3.Enabled = true;
    }

    private void saveWord(Word w)
    {
        if (w.hindiDef == "")
        {
            w.loadHinDefn();
            w.HindiDefLoadedEvent += new Word.hindiDefLoaded(w_HindiDefLoadedEventforHindiSave);
        }
        if (w.engDefinition == "")
        {
            w.loadEngDefn();
            w.engDefnLoadedEvent += new Word.engDefnLoaded(w_engDefnLoadedEventforEnglishSave);
        }
        addToHistory(w);
    }

    void w_HindiDefLoadedEventforHindiSave(Word sender, EventArgs data)
    {
        sender.HindiDefLoadedEvent -= w_HindiDefLoadedEvent1;
        sender.HindiDefLoadedEvent -= w_HindiDefLoadedEventforHindiSave;
    }
    void w_engDefnLoadedEventforEnglishSave(Word sender, EventArgs data)
    {
        sender.engDefnLoadedEvent -= w_engDefnLoadedEventforEnglishSave;
        sender.engDefnLoadedEvent -= w_engDefnLoadedEventforEnglishSave;
    }

    void w_HindiDefLoadedEvent1(Word sender, EventArgs data)
    {
        saveWord(sender);
        sender.HindiDefLoadedEvent -= w_HindiDefLoadedEvent1;
    }

    void w_engDefnLoadedEvent1(Word sender, EventArgs data)
    {
        sender.loadHinDefn();
        sender.HindiDefLoadedEvent += new Word.hindiDefLoaded(w_HindiDefLoadedEvent1);
        sender.engDefnLoadedEvent -= w_engDefnLoadedEvent1;
    }

    void initWord(String query) 
    {
        queryTxt.Text = query;
        w.engWordProp=queryTxt.Text;
        w.loadEngDefn();
        w.loadHinDefn();
        w.engDefnLoadedEvent += new Word.engDefnLoaded(w_engDefnLoadedEvent);
        w.HindiDefLoadedEvent += new Word.hindiDefLoaded(w_HindiDefLoadedEvent);
    }

単語クラス

    public Word(string q)
    {
        wb1 = new WebBrowser();
        wb2=new WebBrowser();
        engWord = q;
        hindiDef = "";
        engDefinition = "";
        flagE = false;
        flagH = false;
        engUrl = "http://oxforddictionaries.com/definition/english/" + q + "?q=" + q;
        hindiUrl = "http://dict.hinkhoj.com/hindi-dictionary.php?word=" + q;
        wb1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted); ;                
        wb2.DocumentCompleted+=new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);
    }

    public delegate void engDefnLoaded(Word sender, EventArgs data);
    public event engDefnLoaded engDefnLoadedEvent;
    protected void onEngDefnLoadCompleated(Word sender, EventArgs data)
    {
        if (engDefnLoadedEvent!=null)
        {
            engDefnLoadedEvent(this,data);
        }
    }


    public void loadEngDefn()
    {
        if (this.engDefinition=="")
        {
  //          wb1 = new WebBrowser();
            wb1.ScriptErrorsSuppressed = true;
            wb1.Url = new Uri(this.engUrl);
        }
        else
        {
            if (engDefnLoadedEvent!=null)
            {
                engDefnLoadedEvent(this, new EventArgs());
            }
        }

    }


    public void loadHinDefn() {
        if (this.hindiDef=="")
        {
    //        wb2 = new WebBrowser();
            wb2.ScriptErrorsSuppressed = true;
            wb2.Url = new Uri(this.hindiUrl);
        }
        else
        {
            if (HindiDefLoadedEvent!=null)
            {
                HindiDefLoadedEvent(this, new EventArgs());
            }
        }

    }
   [NonSerialized] 
    HtmlDocument hd;

    void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {

            if (((WebBrowser)sender).ReadyState == WebBrowserReadyState.Complete)
            {
                hd = ((WebBrowser)sender).Document;
                if (e.Url.ToString() == this.hindiUrl)
                {
                    parsePage(hd.GetElementById("maint"), "hindi");
                    ((WebBrowser)sender).DocumentCompleted -= wb_DocumentCompleted;
                    sender = null;
                }
                else
                {
                    parsePage(hd.GetElementById("entryPageContent"), "eng");
                    ((WebBrowser)sender).DocumentCompleted -= wb_DocumentCompleted;
                    sender = null;
                }

            }                
    }

    private void parsePage(HtmlElement hd, string lan)
    {
        HtmlElementCollection he;
        if (lan == "eng")
        {
            he = hd.GetElementsByTagName("section");
            foreach (HtmlElement item in he)
            {
                this.engDefinition += item.InnerHtml + "<br>";
            }
            flagE = true;
            engDefnLoadedEvent(this, new EventArgs());
            wb1 = null;
            wb1.Dispose();
            return;
        }
        else
        {
            he = hd.GetElementsByTagName("div");
            foreach (HtmlElement item in he)
            {
                if (item.GetAttribute("itemprop") == "itemListElement")
                {
                    this.hindiDef += item.GetElementsByTagName("div")[0].InnerHtml + "<br>";
                }
            }
            flagH = true;
            HindiDefLoadedEvent(this,new EventArgs());
            wb2 = null;
            wb2.Dispose();
            return;
        }
    }

質問: このメモリ リークの問題を解決するにはどうすればよいですか?

サンプル写真 メモリ スナップ 2 つの 4-5 クエリの後。

クエリ 25 ワードの後。

デッドロック

4

2 に答える 2

0

Word クラスのコンストラクターには、次のコードがあります。

wb1 = new WebBrowser();
wb2=new WebBrowser();

WebBrowser クラスは、ローカルの IE バージョンの Web ブラウジング機能の一部をインスタンス化することを目的としています。私の推測では、WebBrowser は IE の一部であり、メモリ消費量が多いと考えられます。 WebBrowser オブジェクトにプール システムを使用できますが、それらの動作を使い捨ての WebClient オブジェクトに置き換えます。

PS ガベージ コレクター システムは微調整されたシステム でありGC.Collect();、コード上でハンマーを使用するようなものです。

于 2013-09-24T19:52:06.997 に答える
0

最初に指摘したいのは、アプリケーションが 300 ~ 400 MB のメモリを使用しているからといって、必ずしもメモリ リークが発生しているとは限らないということです。要求されたページごとにメモリが増加し続け、解放されない場合にのみ、リークが発生します。

次に、問題を診断するために、メモリ プロファイラーを実行する必要があります。Visual Studio の Premium または Ultimate エディションを使用している場合は、メモリ プロファイル機能があります。そうでない場合は、RedGate メモリ プロファイル(14 日間の無料トライアル) または同様のソフトウェアを使用できます。

また、.NET でのリークの最も一般的な原因は、存続期間の短いオブジェクトが、存続期間の長いオブジェクトによって発生したイベントにオブザーバー/ハンドラーとしてアタッチされるイベントの使用であることも付け加えておきます。

于 2013-09-24T19:45:21.220 に答える