Моя программа - это CRM, я использовал панель Ribbon Rad, так много кнопок с изображениями, RadGridView (некоторые из которых содержат изображения) и многие другие элементы управления, содержащие изображения. Это родительская/дочерняя программа mdi.
Во многих случаях при загрузке дочернего mdi или работе с некоторыми видами сетки программа зависает и дает мне эту ошибку:
OutOfMemoryException occurred in System.Drawing.dll
Я пробовал GC.Collect()
на определенных участках, но не добился успеха. Для установки изображений нет кода! например, для установки изображения для кнопки я использовал свои свойства в visual studio. Я установил все остальные управляющие изображения таким образом, используя панель свойств в визуальном режиме.
и это некоторые коды дизайнеров, относящиеся к чертежу:
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, который содержит Ribbon Bar.
и это полная трассировка стека:
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();
. Но, как сказано в комментариях, диспетчер задач GDI objects
будет увеличиваться и увеличиваться до 10000
объектов, а затем приложение будет аварийно.
ОБНОВЛЕНО: САМЫЙ НОМЕР
Кажется, я нашел часть, которая вызывает наибольшее GDI objects
. В каждой форме есть некоторые элементы управления, такие как текстовые поля, выпадающий список и т.д. Я установил для них некоторые правила, например, если пользователь вводит текстовое поле, его задний цвет должен быть желтым, а после отпуска он должен быть белым снова. Таким образом, существует основной метод, который я вызываю в форме загрузки для грамотности через все элементы управления и поиска целевых и добавления, например, ввода и исключения событий с определенными правилами. что-то вроде этого:
private void FormCustomerList_Load(object sender, EventArgs e)
{
ClassCRMControls.AddEventHandler(this);
}
и внутри ClassCRMControls
class:
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);
}