2017-11-02 8 views
13

私のプログラムはCRMです。私はRad Ribbon Barを使用していましたので、画像がたくさんあるボタン、RadGridView(画像を含む列)画像。これはmdiの親子プログラムです。Main()メソッドでSystem.Drawing例外が発生しました - C#

OutOfMemoryException occurred in System.Drawing.dll 

は、私は特定の部分が、ノー成功にGC.Collect()を試してみました:そう多くのケースで

Just an Example of RibbonBar

MDI子をロードしたり、いくつかのグリッドでの作業中は、プログラムがハングし、私は、このエラーを与えるビュー。画像を設定するためのコードはありません!たとえば、ボタンの画像を設定するために、私はそのプロパティをVisual Studioで使用しました。私はビジュアルモードのプロパティパネルを使って、このように他のすべてのコントロールイメージを設定しました。

enter image description here

及びこれらの図面に関連するいくつかのデザイナーのコードです:

btnCustomerList.Image = global::MyApp.Properties.Resources.CustomerList32; 

    gridViewCommandColumn1.Image = global::MyApp.Properties.Resources.ViewShop32; 

とエラーがアプリで作業しながら、後に来るとき、それはProgram.csにし、ラインApplication.Run(new MainForm());に表示されます。

static void Main() 
    { 
     AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", AppDomain.CurrentDomain.BaseDirectory + "\\Settings.config"); 
     bool ok; 
     Mutex m = new Mutex(true, WindowsIdentity.GetCurrent().Name.ToString().Split('\\')[1] + "MyApp", out ok); 
     if (ok) 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 

      // The Error will cause HERE 
      Application.Run(new MainForm()); 

      GC.KeepAlive(m); 
     } 
     else 
      Application.Exit(); 
    } 

MainFormは、リボンバーを含むmdi親である。 これは完全なスタックトレースです:

at System.Drawing.Image.FromHbitmap(IntPtr hbitmap, IntPtr hpalette) 
at System.Drawing.Image.FromHbitmap(IntPtr hbitmap) 
at System.Drawing.Icon.ToBitmap() 
at System.Windows.Forms.ThreadExceptionDialog..ctor(Exception t) 
at System.Windows.Forms.Application.ThreadContext.OnThreadException(Exception t) 
at System.Windows.Forms.Control.WndProcException(Exception e) 
at System.Windows.Forms.Control.ControlNativeWindow.OnThreadException(Exception e) 
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) 
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 
at System.Windows.Forms.Application.Run(Form mainForm) 
at MyApp.Program.Main() in d:\\MyApp\\Application\\MyApp\\Program.cs:line 36" 

UPADTED:

リボンバーのボタンをクリックしてmdi-childrenを呼び出すためのコードはここにある:

private void btnCustomerList_Click(object sender, EventArgs e) 
{ 
    OpenForm(new FormCustomerList(), "Customer List"); 
} 

private void btnCustomerRelated_Click(object sender, EventArgs e) 
{ 
    OpenForm(new FormCustomerRelated(), "Customer Related"); 
} 

ここではOpenForm方法であり、

private void OpenForm(Form formType, string Caption) 
{ 
    foreach (Form nform in Application.OpenForms) 
    { 
     if (nform.GetType() == formType.GetType()) 
     { 
      nform.Activate(); 
      return; 
     } 
    } 
    this.MdiChildren.OfType<Form>().ToList().ForEach(x => x.Dispose()); 
    GC.Collect(); 

    Form form = formType; 
    form.MdiParent = this; 
    form.Dock = DockStyle.Fill; 
    form.Show(); 
    this.Text = Caption; 
} 

およびすべてのmdi子供のフォームコンストラクタ、InitializeComponent();の後にもGC.Collect();を書きました。しかし、コメントに記載されているように、10000オブジェクトまでタスクマネージャのGDI objectsが増えて増加し、アプリケーションがクラッシュします。

UPADTED:MOST ISSUE

私が最もGDI objectsの原因となる部分を発見したようです。どのフォームでも、テキストボックス、ドロップダウンリストなどのコントロールがいくつかあります。例えば、ユーザーがテキストボックスを入力した場合、その背後の色は黄色でなければなりません。だから私はすべてのコントロールを理解し、ターゲットを見つけて、定義されたルールでイベントを入力したり離したりするなど、フォームロードで呼び出すメインメソッドがあります。

private void FormCustomerList_Load(object sender, EventArgs e) 
{ 
    ClassCRMControls.AddEventHandler(this); 
} 

ClassCRMControlsクラス内部:このような何か

public static void AddEventHandler(Control parent) 
{ 
    foreach (Control c in parent.Controls) 
    { 
     if (c.GetType() == typeof(RadTextBox)) 
     { 
      c.Enter += new EventHandler(ClassCRMControls.EnterEvent); 
      c.Leave += new EventHandler(ClassCRMControls.LeaveEvent); 
     } 
     else 
      AddEventHandler(c); 
    } 
} 

private static void EnterEvent(object sender, EventArgs e) 
{ 
    (sender as RadTextBox).TextBoxElement.TextBoxItem.BackColor = Color.FromArgb(255, 251, 147); 
} 

private static void LeaveEvent(object sender, EventArgs e) 
{ 
     (sender as RadTextBox).TextBoxElement.TextBoxItem.ResetValue(LightVisualElement.BackColorProperty, ValueResetFlags.Local); 
} 
+0

ログの完全なスタックトレースは、多分それはいくつかの手がかりを提供します。 – Evk

+2

Hmya、プログラムに不正なハンドルリークがあります。それは非常に悪いので、例外ダイアログでさえもはや表示することはできません。タスクマネージャの[プロセス]タブに表示されるものです。あなたはそれが着実に増加し、それは10000誰もがこれらの画像を配置しないためのあらゆる賞を獲得しないが、それは致命的ではありません到達したときにショーが終わって参照してくださいよ、GDIオブジェクトの列を追加します。すでにGC.Collect()を試してみたと言いますが、ファイナライザのスレッドがデッドロックしている可能性があります。アンマネージデバッグを有効にし、それが何をしているのかを調べます。 USER()はControls.Clearを使用することによって生じたWinformsの中の別の伝統的なバグがそれらをされて漏れて、列オブジェクト()または削除で –

+1

も見えます。 –

答えて

5

私は、問題の原因を発見した、それは私があまりにもグリッドや他のコントロールのために使用されるカスタムアニメーションカーソルました。

this.Cursor = ClassObjects.CreateAnimatedCursor("C:\\aniCur.ani")); 

私は、ファイルから、私はどのような方法でそれを使用するたびに、このカーソルをロードしているので、GDI Objectsが作成されてしまった、より多くの:私はこのようにそれを初期化します。

だから、このような各形態の)(主public static cursor宣言:

public static Cursor animCur = ClassObjects.CreateAnimatedCursor("C:\\aniCur.ani")); 

した後、私はちょうどフォームからこのオブジェクトpublic static cursorを参照して、このカーソルを使用する必要があるたびに。

this.Cursor = MainForm.animCur; 

それだそれ:)

私はそれを見つけましたか?私はそれらを疑ういくつかのコードを削除(コメント)しようとすると、タスクマネージャのGDI objectsをチェックしました。いくつかのテストの後で、新しいカーソルオブジェクトの無限のロードが問題を引き起こしていることが明らかになりました。

+3

これは非常に有用な答えではありません。確かにこのQ + Aの今後の読者はまったく同じ問題を抱えず、このハンドルリークの原因をどのように発見したか知りたいと思うでしょう。 GC *が漏れを正しく回避できるように、これを正しく実行することを検討してください。サンプルコード[here here](https://stackoverflow.com/a/4306984/17034)では、 "ownHandle"フィールドのハックがそれを処理します。 –

+1

将来の読者のために、OPは彼のGDIオブジェクト数分析を含むように編集しました。 Hansはアプリケーションの使用中にGDI Countを観察して、ここでそれについて議論しました(https://stackoverflow.com/a/8306253/495455)。これを行う方法に関する詳細と手順があります。(0120-13-0111) –

+1

これは、将来の読者に「OutOfMemoryException」にはより多くの情報源があることを伝えているので、これは有用な答えですメモリ状態からの*ちょっとしたエラーよりも。ここにはGDIハンドルのリークがありました。そして、これが最終的に同じ例外を引き起こす場合は、あなたに説明したことは有益な状況です。しかし、SOには、これらのことを詳細に説明する他のQ&A記事があります。これがこの質問とその答えを無効にするわけではありませんが、重複としてそれを閉じることは有益かもしれません。 –

3

OutOfMemoryExceptionsための複数の理由が考えられます。私はそれらのうちの6つを説明したin another question。この場合

は、コメントや編集した後、それは、GDIの問題が同様に発生していることが明らかになりました。あなたは、タスクマネージャで追加の列を示すことによって、これらの問題を検出することができます:それはまた、あなたの失われてしまったGDIハンドルのタイプを伝えるため

GDI objects shown in Task Manager

GDIViewは、GDIリーク分析のためのはるかに優れたアプリケーションです。絶対カウンタと相対カウンタもありますので、特定のアクション中に失われるカウンタの数を確認できます。

GDIView details

GDIの数がcan be configured in Registryを処理します。それを恒久的な解決策として使用しないでください。代わりに、GDIViewからの追加情報で、GDIオブジェクトをリークするコードを見つけます。

あなたがGDIハンドルの制限に実行すると、アプリケーションは一般的に悪い探して起動します:物事は、任意のより多くを描いて、あなたはいくつかの場所で黒い長方形を取得していません。ただし、この動作は必要ありません。 OPの場合、黒い長方形は説明の一部ではありませんでした。この例外の

関連する問題