No hay memoria suficiente o no lo suficiente mangos?
-
28-09-2019 - |
Pregunta
Estoy trabajando en un proyecto a gran escala en la que se ha proporcionado una costumbre (bastante bueno y robusto) marco y tenemos que utilizar eso para aparecer formas y puntos de vista.
Hay StrategyEditor clase abstracta (derivado de alguna clase en marco) que se crea una instancia cada vez que se abre un nuevo StrategyForm.
StrategyForm
(un marco de ventana personalizada) contiene StrategyEditor
.
StrategyEditor
contiene StrategyTab
.
StrategyTab
contiene StrategyCanvas
.
Esta es una pequeña parte de las grandes clases de aclarar que hay muchos objetos que serán creados si un objeto StrategyForm se asigna en la memoria en tiempo de ejecución. Mi componente posee todas estas clases mencionadas anteriormente, excepto StrategyForm
cuyo código no está en mi control.
Ahora, en tiempo de ejecución, el usuario abre muchos objetos de estrategia (que la creación de activadores del nuevo objeto StrategyForm.) Después de crear aprox. 44 objetos de estrategia, vemos que las asas objeto de usuario (utilizaré UOH de aquí en adelante) creados por los alcances de aplicación hasta alrededor de 20k +, mientras que en el registro de la cantidad predeterminada de mangos es 10k. Más información acerca de objetos de usuario aquí Testing. en diferentes máquinas dejado claro que el número de estrategia de objeto abierto es diferente para el mensaje a pop-up -. en una m / c si es 44, entonces puede ser 40 en otro
Cuando vemos el mensaje emergente, esto significa que la aplicación va a responder con lentitud. Se pone peor con unos cuantos objetos y luego la creación de marcos de ventanas y objetos posteriores fallan.
Primero pensamos que era cuestión por insuficiente memoria. Pero entonces leer más sobre new
en C # ayudaron en la comprensión de que una excepción se produce si la aplicación no tiene memoria. Esto no es un problema de memoria a continuación, me siento (administrador de tareas también mostró 1,5 GB + memoria disponible.)
M / C especificaciones
Core 2 Duo a 2 GHz +
4 GB de RAM
80 GB + espacio libre en disco para el archivo de la página
juego de memoria virtual: 4000 - 6000
Mis preguntas
Q1. Se ve este como un problema de memoria y yo estoy equivocado que no es?
Q2. Hace este punto hasta el agotamiento de UOHs libres (que a mí el pensamiento) y que está dando como resultado el fracaso de la creación de identificadores de ventana?
Q3. ¿Cómo podemos evitar la carga de un objeto StrategyEditor
(más allá de un umbral, manteniendo un ojo en el uso actual de UOHs)? (Que ya sabemos cómo buscar a número de UOHs en uso, así que no vayas allí.) Tenga en cuenta que la llamada a new StrategyForm()
está fuera del control de mi componente.
Q4. Estoy algo confundido - ¿Cuáles son Los mangos a los objetos de usuario exactamente? MSDN está hablando de cualquier objeto que creamos o sólo algunos objetos específicos como identificadores de ventana, manijas, tiradores de cursor icono?
Q5. ¿Qué causa exactamente a utilizar hasta un LiOH? (Casi el mismo que el Q4)
Me sería muy agradecidos a todos los que me puede dar algunas respuestas informadas. ¡Muchas gracias! :)
[Actualización]
Sobre la base de la respuesta Stakx, tenga en cuenta que las ventanas que se están abriendo, estarán cerradas por sólo el usuario. Esta es una especie de MDI situación aplicación donde se abren demasiados niños ventanas. Así, Dispose
no se puede llamar siempre que queramos.
Solución
Q1
Parece que usted está tratando de crear demasiados controles de interfaz de usuario al mismo tiempo. Incluso si no hay memoria de la izquierda, que está quedando sin asas. Vea a continuación una breve, pero la explicación bastante técnico.
Q4
entiendo un objeto de usuario para ser cualquier objeto que forma parte de la interfaz gráfica de usuario. Al menos hasta que Windows XP, la interfaz de usuario de Windows API residía en USER.DLL
(una de las DLL básicos que componen de Windows). Básicamente, la interfaz de usuario se compone de "ventanas". Todos los controles, como botones, cuadros de texto, casillas de verificación, son internamente la misma cosa, a saber, "ventanas". Para crearlos, que se podría llamar la función API de Win32 CreateWindow
. Esa función sería entonces devuelve un recurso a la "ventana" creado (elemento de interfaz de usuario, o "objeto de usuario").
Así que supongo que a mango objeto de usuario es un identificador devuelto por esta función. (Winforms se basa en la antigua API de Win32 y por lo tanto utilizar la función CreateWindow
.)
Q2
En realidad no se puede crear tantos controles de interfaz de usuario que desee. Todas las manijas del recuperados a través obligada CreateWindow
en algún momento ser liberados. En Winforms, la forma más fácil y segura de hacer esto es mediante el uso del bloque using
o llamando Dispose
:
using (MyForm form = new MyForm())
{
if (form.ShowDialog() == DialogResult.OK) ...
}
Básicamente, todo System.Windows.Forms.Control
puede Dispose
d, y debe desecharse. A veces, eso se hace de forma automática, pero no se debe confiar en él. Siempre Dispose
sus controles de interfaz de usuario cuando ya no los necesita.
Nota sobre Dispose
para las formas modales y no modales:
- formas modales (mostrados con
ShowDialog
) son no dispuestos de forma automática. Usted tiene que hacerlo usted mismo, como se demuestra en el ejemplo código de seguridad. - formas modales (se muestra con
Show
) están dispuestos automáticamente para usted, ya que no tienen control sobre cuándo será cerrado por el usuario. No hay necesidad deDispose
explícitamente llamada!
Q5
Cada vez que se crea un objeto de interfaz de usuario, Winforms internamente realiza llamadas a CreateWindow
. Eso es cómo se asignan los mangos. Y no están liberados hasta que se realice una llamada correspondiente a DestroyWindow
. En Winforms, esa llamada se activa a través del método Dispose
de cualquier System.Windows.Forms.Control
. (Nota: Mientras estoy farily seguro sobre esto, en realidad estoy adivinando un poco Puede que no sea 100% correcto Tener un vistazo a internos Winforms usando Reflector revelaría la verdad...)
Q3
Si se asume que su StrategyEditor
crea un grupo masivo de los controles de interfaz de usuario, no creo que pueda hacer mucho. Si no se puede simplificar el que el control (con respecto al número de controles secundarios que genera), entonces parece que está atrapado en la situación en la que se encuentre. Simplemente no puede crear un número infinito de los controles de interfaz de usuario.
Se podría, sin embargo, mantener un registro de cuántas StrategyEditor
s se abren en cualquier momento uno (incrementar un contador cada vez que uno se crea una instancia, y disminuirla cuando uno está cerrado - se puede realizar un seguimiento de este último utilizando el evento FormClosing
/ FormClosed
de un formulario, o en el método Dispose
de un control). Posteriormente, se podría limitar el número de StrategyEditor
s abiertos simultáneamente a un número fijo, digamos 5. Si se supera el límite, se podría producir una excepción en el constructor, por lo que no hay más casos se crean. Por supuesto que no puedo decir si StrategyForm
va a manejar una excepción de su constructor StrategyEditor
así ...
public class StrategyEditor : ...
{
public StrategyEditor()
{
InitializeComponent();
if (numberOfLiveInstances >= maximumAllowedLiveInstances)
throw ...;
// not a nice solution IMHO, but if you've no other choice...
}
}
En cualquier caso, lo que limita el número de StrategyEditor
s instanciados parece como una solución temporal a mí y no va a resolver el problema real.