PDA

Ver la Versión Completa : Iniciar un TThread en un Form crear en runtime


joseprad
03-06-2013, 15:59:52
Hola amigos:

Tengo un problema que no consigo resolver, ni encontró información en Internet.

Tengo un programa principal, que ha modo de menú general, abre diferentes formularios con el procedimiento:

with TForm1.Create(self) do begin
showModal;
free;
end;


Esto, me funciona perfectamente hasta que en un formulario abierto en tiempo de ejecución, intento crear un nuevo hilo.

El programa es una prueba de programa multi hilo, que me baje de Internet.

procedure TReloj.ActualizaTexto;
begin
Form8.lbl1.Caption:=IntToStr(Hora);
end;

procedure TReloj.Execute;
begin
Salir := False;
Hora := 0;
while not Salir do begin
Synchronize(ActualizaTexto);
sleep(1000);
inc(Hora);
end;
end;


Cuando lo ejecuto se ejecuta synchronize y pasa a ejecutar ActualizarTexto me da el siguiente error:
'Access violation at address 00A16CD2 in module 'MenuAplicacion'.Read of address '00000390'.

En cambio si lo ejecuto como programa principal, funciona perfectamente y no da ningún error.

Agradeceré cualquier ayuda

Neftali [Germán.Estévez]
03-06-2013, 17:40:57
No parece que en ese código exista ningún problema, pero habría que ver el código completo de la llamada y del Thread.
La mayoría de los problemas con hilos llegan por intentar acceder a elementos que no están definidos en el thread (sin sincronizar).

Con esto que pones es difícil....

joseprad
09-06-2013, 09:50:50
Lo curioso es que si arranco directamente el programa que ejecuta el TThread, funciona correctamente.
El error lo da si genero el formulario en runTime

nlsgarcia
10-06-2013, 04:32:41
joseprad,



...El programa es una prueba de programa multi hilo...

...Cuando lo ejecuto se ejecuta synchronize y pasa a ejecutar ActualizarTexto me da el siguiente error: 'Access violation at address 00A16CD2 in module 'MenuAplicacion'.Read of address '00000390'...

...si lo ejecuto como programa principal, funciona perfectamente...

...si arranco directamente el programa que ejecuta el TThread, funciona correctamente...
Pregunto:

1- ¿El formulario Form8 esta instanciado al momento de la falla?

2- ¿Puedes colocar el código es cuestión para analizar el problema?

Espero sea útil :)

Nelson.

joseprad
16-06-2013, 13:59:58
Hola Nelson.

Te adjunto el código completo del Form8

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, JfLabel, JfButtons, ExtCtrls;

type
TForm8 = class(TForm)
btoIniciar: TJfBitBtn;
btoParar: TJfBitBtn;
lbl1: TLabel;
procedure btoIniciarClick(Sender: TObject);
procedure btoPararClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

TReloj = class(TThread)
private
Hora: Integer;
Salir: Boolean;
procedure ActualizaTexto;
protected
procedure Execute; override;
procedure Terminar;
end;

var
Form8: TForm8;
Reloj: TReloj;
Corriendo: Boolean;

implementation

{$R *.dfm}
{ TReloj }

procedure TReloj.ActualizaTexto;
begin
Form8.lbl1.Caption:=IntToStr(Hora);
end;

procedure TReloj.Execute;
begin
Salir := False;
Hora := 0;
while not Salir do begin
Synchronize(ActualizaTexto);
sleep(1000);
inc(Hora);
end;
end;

procedure TReloj.Terminar;
begin
Salir := true;
end;

procedure TForm8.btoIniciarClick(Sender: TObject);
begin
if not Corriendo then begin
Reloj := TReloj.Create(False);
Corriendo := true;
end;

end;

procedure TForm8.btoPararClick(Sender: TObject);
begin
if Corriendo then begin
Reloj.Terminar;
Reloj.Free;
Corriendo := False;
end;
end;

procedure TForm8.FormCreate(Sender: TObject);
begin
Corriendo := False;
end;

end.

Este programa que no es mas que un contador, funciona perfectamente.

Pero si lo arranco desde otro programa con:


with TForm8.Create(self) do begin
ShowModal;
Free;
end;


entonces me da el error.

Saludos

beginner01
16-06-2013, 21:51:03
Hola Nelson.

Te adjunto el código completo del Form8

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, JfLabel, JfButtons, ExtCtrls;

type
TForm8 = class(TForm)
btoIniciar: TJfBitBtn;
btoParar: TJfBitBtn;
lbl1: TLabel;
procedure btoIniciarClick(Sender: TObject);
procedure btoPararClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

TReloj = class(TThread)
private
Hora: Integer;
Salir: Boolean;
procedure ActualizaTexto;
protected
procedure Execute; override;
procedure Terminar;
end;

var
Form8: TForm8;
Reloj: TReloj;
Corriendo: Boolean;

implementation

{$R *.dfm}
{ TReloj }

procedure TReloj.ActualizaTexto;
begin
Form8.lbl1.Caption:=IntToStr(Hora);
end;

procedure TReloj.Execute;
begin
Salir := False;
Hora := 0;
while not Salir do begin
Synchronize(ActualizaTexto);
sleep(1000);
inc(Hora);
end;
end;

procedure TReloj.Terminar;
begin
Salir := true;
end;

procedure TForm8.btoIniciarClick(Sender: TObject);
begin
if not Corriendo then begin
Reloj := TReloj.Create(False);
Corriendo := true;
end;

end;

procedure TForm8.btoPararClick(Sender: TObject);
begin
if Corriendo then begin
Reloj.Terminar;
Reloj.Free;
Corriendo := False;
end;
end;

procedure TForm8.FormCreate(Sender: TObject);
begin
Corriendo := False;
end;

end.

Este programa que no es mas que un contador, funciona perfectamente.

Pero si lo arranco desde otro programa con:


with TForm8.Create(self) do begin
ShowModal;
Free;
end;


entonces me da el error.

Saludos


Hola.

Si te fijas en el código en rojo estas utilizando la variable Form8 que hace referencia a la clase TForm8, a la cual no le estas asignando ningún valor por lo que tiene un valor nil o nulo y si intentas hacer referencia a esta (invocar métodos o acceder a sus propiedades) Delphi te devolverá un error "Acces Violation". Una solución para tu caso es asignarle la referencia del formulario creado para que puedas acceder a él.

{
Creamos el formulario y le asignamios la referencia a la variable Form8.
}
Form8 := TForm8.Create(self);
with Form8 do
try
ShowModal;
finally
Free;
end;



try..finally (http://www.delphibasics.co.uk/RTL.asp?Name=Finally)

joseprad
22-06-2013, 18:29:24
Muchas gracias amigo.
Como dicen en mi tierra siempre ven mas cuatro ojos que dos.