Autor: Zou Fei
Correo electrónico: [email protected]
Página de inicio: http://www.atechsoft.com/people/zouf/ En el proceso de uso de Delphi, inevitablemente encontrará muchos problemas extraños, y la documentación de Delphi también es sorprendentemente escasa, por lo que solo puedo resumirla lentamente por mí mismo. , entonces los hay (dado que son solo detalles dispersos, no dediqué mucho esfuerzo a escribir, puede que sea un poco complicado, pero debería ser comprensible ;-)). Si: 1. Si tiene una mejor solución para el siguiente problema, dígaselo a mí y a mis amigos en csdn. 2. Si tiene otras preguntas, enumere los problemas y sus respuestas y dígaselo a mí y a mis amigos en csdn. ¡La comunicación lo crea todo!
Texto: P: Si un formulario creado en Delphi DLL es ShowModal en Exe, aparecerán dos íconos en la barra de tareas. ¿Cómo solucionar este problema? R: El siguiente es un método típico para colocar un formulario en una DLL: DLL: función ShowFrm: TModalResult; stdcall;beginForm1 := TForm1.Create(Nil); función ShowFrm: TModalResult; llamada estándar; 'TestDLL.dll';…begin…ShowFrm;…end. El formulario en la DLL creada de esta manera mostrará otro ícono con la aplicación principal. La razón es que se creará otra aplicación para la DLL en Delphi. La aplicación mostrará un icono en la barra de tareas. Solución: pase la aplicación del EXE principal a la DLL de la aplicación principal, de la siguiente manera: DLL: función ShowFrm(aplicación: TApplication): TModalResult; stdcall;varoldApp: TApplication;beginoldApp := Aplicación;Aplicación := aplicación;Form1 : = TForm1.Create(Nil);tryForm1.ShowModal;finallyForm1.Free;end;Aplicación := oldApp;end;EXE principal: función ShowFrm(aplicación: TApplication): TModalResult; stdcall; externo 'TestDLL.dll';…begin…ShowFrm(Aplicación);…end. Todavía hay algunas diferencias, mira el código en Forms.pas: constructor TApplication.Create(AOwner: TComponent);begin…si no es IsLibrary entonces CreateHandle;…end;Se puede saber que la aplicación en la DLL no tiene un Handle, por lo que no se realizará el procesamiento del bucle de mensajes, lo cual también es correcto. P: ¡A menudo ocurren problemas con las DLL en Delphi! R: La razón por la que ocurre el problema es por el propio mecanismo de administración de memoria de Delphi. Por ejemplo: cree un objeto en una DLL: x := TClass.Create(Application). En este momento, Delphi liberará automáticamente El espacio de direcciones puede haber caducado (los diferentes sistemas operativos serán diferentes), por lo que la operación de liberación de x lo hará; provocar una excepción. Otro ejemplo: cree un objeto en EXE y pase una DLL como una variable local en la DLL. Cuando se destruye la DLL, Delphi liberará automáticamente todas las variables que están fuera de alcance, por lo que si usa este objeto en EXE nuevamente, se generará un objeto. Se lanzará una excepción. En términos generales, el problema se debe al mecanismo de administración de memoria del compilador "inteligente" Delphi y al mecanismo de agregar/descargar DLL de Windows, lo que genera conflictos de acceso a la memoria en DLL y EXE. Solución: (La mayoría de los problemas se pueden evitar siempre que siga los siguientes principios) 1. Entre DLL y EXE, intente no utilizar el mecanismo de administración automática de memoria de Delphi. El programador es responsable del ciclo de vida del objeto. Por ejemplo: para lo anterior x := TClass.Create(Application); TClass.Create(nil); De esta manera, la aplicación ya no lo liberará. Por supuesto, el programador debe liberarlo él mismo. 2. Intente evitar tener diferentes punteros apuntando al mismo objeto entre la DLL y el EXE. Por ejemplo, en DLL, x apunta al objeto TClass y en EXE, y apunta al objeto TClass. De esta manera, la liberación de memoria en cualquier lado hará que la memoria del otro lado no sea válida. 3. Otros... P: Un subproceso que realiza tareas periódicas necesita pausarse por un momento y luego continuar ejecutándose, pero ¿qué pasa si es necesario detener el subproceso en ese momento (por ejemplo, el proceso ha finalizado)? R: Solución 1: Realice un bucle periódico a través de Sleep en el hilo. (Si el hilo se pausa durante la suspensión, el hilo no se puede resucitar mediante Resume y otros métodos). Finalice el hilo a través de KillThread. Este es el método más simple, pero es demasiado tosco y puede causar problemas (KillThread es una API no recomendada para Windows) Solución 2: suspender en el hilo, pasar un temporizador fuera del hilo y reanudar de vez en cuando. El código es el siguiente: // ThreadPRocedure Execute;begin while not Terminated dobegin... // Código de procesamiento Suspend;end;end;// Exterior // Procedimiento del temporizador OnTimer(Sender: Tobject);beginthd.Resume;end;// Para finalizar el hilo Coloque...thd.Resume;thd.Terminate;thd.WaitFor; Generalmente, después de finalizar el hilo, debes usar WaitFor para confirmar que el hilo realmente ha terminado. ...Problema: El acoplamiento entre el hilo y el exterior es demasiado fuerte, e incluso el ciclo de operación del hilo debe determinarse mediante un temporizador externo. Solución tres (esta es la mejor manera que se me ocurrió): pausar el hilo a través de un semáforo. // ThreadTMyThread = clase(TThread)Evento privado: TEvent;procedimiento protegido Ejecutar; anular;constructor público Create(loginInfo: TLoginInfo); sobrecarga del destructor SetEvent;end;{ TMyThread }constructor TMyThread.Create(loginInfo: TLoginInfo); comenzar evento: = TEvent.Create (nulo, verdadero, verdadero, 'EventName');end;destructor TMyThread.Destroy;begin Event.Free; heredado;end;procedimiento TMyThread.Execute;begin heredado; mientras no esté terminado, comience // ... Event.ResetEvent; end;end;procedure TMyThread.SetEvent;begin Event.SetEvent;end;Para programas que necesitan interrumpir subprocesos, solo el siguiente código es suficiente: comenzar …thd.Terminate;thd.SetEvent;thd.WaitFor;…end;