2008-11-08 13 views
9

si se llama a Form.Release después de usar el formulario, liberará toda la memoria relacionada, pero no establecerá la variable de forma en nil.Form.Release + NIL

if not assigned (Form1) then 
    begin 
    Application.CreateForm(Tform1, Form1); 
    try 
     // Do something 
    finally 
     Form1.Release 
    end; 
    end; 

Para poder volver a llamar al mismo código, Form1 debería establecerse en cero en algún momento. A partir de la descripción de lanzamiento no puedo hacer

Form1 := nil; 

justo después de lanzamiento, ya que el procedimiento de liberación volverá directamente después de ser llamado y antes de que el formulario es realmente liberado. No puedo detectar cuándo finaliza Form.Release para establecer la forma var a nil.

¿Cuál es la mejor manera de hacerlo?

Holger

Respuesta

14

Ponga la línea

Form1 := nil; 

justo después de la llamada a Release.

La versión acaba de publicar un mensaje CM_RELEASE en el formulario que permite al formulario finalizar lo que hay en su cola (controladores de eventos) antes de manejar el mensaje CM_RELEASE, lo que significa que normalmente solo se llama a Free.
Por lo tanto, después de llamar a Release, no debe suponer que la variable Form todavía apunta a un Formulario válido, por lo que pone nil en la variable.

0

En Delphi Win32, la forma apropiada de objetos libres es llamar

FreeAndNil(Form1) 

Esto hace dos puestos de trabajo en una sola llamada.

Sin embargo, tengo la sensación de que su pregunta es más de lo que parece. ¿Estás usando Delphi para .NET? Y si es así, ¿qué versión?

+1

Excepto que no se aplica a las formas en las que no se utiliza de forma gratuita, pero la versión ... –

+0

Roddy, estoy utilizando Delphi Win32 (lo siento por no mencionar). Por lo que yo entiendo, para un formulario, Release hace muchas más tareas que solo un FreeAndNil simple, que no liberaría los componentes que pertenecen al formulario. ¿Es esto correcto? – Holgerwa

+0

Sí, Release hace más, pero solo para diferir la llamada de Free. No necesita llamar a Devolución gratuita, por lo que no necesita llamar a Liberación y puede llamar gratis. Consulte también http://stackoverflow.com/questions/274523/formrelease-nil#274734 –

11

La versión es solo un (potencialmente) diferido Gratis. Lo primero que debe hacer después de llamar a Release es anotar la variable.
Entonces, estará seguro incluso si algún código intenta hacer referencia a Form1 antes de que se destruya realmente. En un caso como en tu código, solo recrearía de forma segura otro Form1 para el nuevo uso sin molestar al que se está destruyendo.

2

Como se menciona La liberación es solo un diferido Gratis para un formulario para usar si quiere cerrar/Libre. Aparte de diferir, no hace nada diferente de Release. Entonces no sirve de nada llamar a Release en ese ejemplo. Llamar gratis parece ser más lógico. Y puede configurarlo en cero después de llamar a Free o usar FreeAndNil.

Si aún desea utilizar Release, está bien. Solo establecer el valor de la variable a nil funciona. Hacer eso no hace que el foro se comporte de manera diferente. Pero recuerde que en este caso es más eficiente y más determinista llamar a Free en lugar de Release. Mi preferencia es usar solo Release donde realmente se necesite.

3

Por sólo podría siempre llaman a esto:

procedure FreeOrReleaseAndNil(var Obj); 
var 
    Temp: TObject; 
begin 
    Temp := TObject(Obj); 
    Pointer(Obj) := nil; 
    if Temp is TCustomForm then 
    TCustomForm(Temp).Release 
    else 
    Temp.Free; 
end; 

asegúrese de comprobar el tipo después de echar a un TObject como no se puede probar el tipo de Obj. Este debería estar seguro ya que, como Free, Release no es virtual.

+0

Jim, puede evitar la prueba en Asignado, ya que (Temp es TAnyType) siempre devolverá False cuando Temp es nulo. –

+0

Se arregló. Gracias. –